WinUI 3 (0.8.1)、C++/WinRT (2.0.210714.1)、桌面 - 使用“BindingOperations::SetBinding(...)
WinUI 3 (0.8.1), C++/WinRT (2.0.210714.1), Desktop - Using "BindingOperations::SetBinding(...)
我将 Xaml 中的 ListBox
绑定到 NetworkViewModel
实例,该实例包含 NodeViewModel
实例的集合。 NodeViewModel
实例应显示在 canvas 的 X 和 Y 位置,由 NodeViewModel
.
提供
我想绑定 ListBoxItem
的 Canvas。左和Canvas。顶部到 X 和 Y。我假设在 WinUI 中不可能在样式中使用绑定。解决方法可以是一个 helper class,它带有绑定源路径的附加属性。它在助手 属性 的 PropertyChangedCallback
中创建代码隐藏绑定。但是绑定不起作用,为什么?
void BindingHelperNodes::OnBindingPathPropertyChanged( winrt::Microsoft::UI::Xaml::DependencyObject const& d,
winrt::Microsoft::UI::Xaml::DependencyPropertyChangedEventArgs const& e )
{
if(Microsoft::UI::Xaml::Controls::ListBoxItem item{ d.try_as<Microsoft::UI::Xaml::Controls::ListBoxItem>() })
{
Microsoft::UI::Xaml::Controls::Canvas::LeftProperty;
Microsoft::UI::Xaml::Data::Binding binding;
binding.Mode( Microsoft::UI::Xaml::Data::BindingMode::OneWay );
Microsoft::UI::Xaml::PropertyPath propertyPath( L"Y" );
binding.Path( propertyPath );
Microsoft::UI::Xaml::Data::RelativeSource relativeSource;
relativeSource.Mode( Microsoft::UI::Xaml::Data::RelativeSourceMode::Self );
binding.RelativeSource( relativeSource );
Microsoft::UI::Xaml::Data::BindingOperations::SetBinding(
d,
Microsoft::UI::Xaml::Controls::Canvas::LeftProperty(),
binding);
//item.SetBinding( Microsoft::UI::Xaml::Controls::Canvas::LeftProperty(), binding );
}
}
<Grid>
<Grid.Resources>
<ResourceDictionary>
<Style x:Name="listBoxItemContainerStyle2" TargetType="ListBoxItem">
<Setter Property="Canvas.Left" Value="0"/>
</Style>
</ResourceDictionary>
</Grid.Resources>
<ListBox Grid.Row="1" ItemsSource="{x:Bind mainViewModel.NetworkViewModel.Nodes, Mode=OneWay}"
>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="local:BindingHelperNodes.CanvasLeftBindingPath" Value="X"/>
</Style>
</ItemsControl.ItemContainerStyle>
<ListBox.Template>
<ControlTemplate TargetType="ListBox">
<ItemsPresenter />
</ControlTemplate>
</ListBox.Template>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Background="Transparent" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate x:DataType="local:NodeViewModel">
<Grid
Width="120"
Height="60"
>
<!-- This rectangle is the main visual for the node. -->
<Rectangle
Stroke="Black"
Fill="White"
RadiusX="40"
RadiusY="40"
/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
幸运的是我发现了问题!真正的问题是第 13 行中对 SetBinding() 的调用,它没有任何效果。但是我居然忘了在IDL文件中设置属性“[Microsoft.UI.Xaml.Data.Bindable]”!
IDL 文件:
namespace NetworkView
{
[Microsoft.UI.Xaml.Data.Bindable]
runtimeclass NodeViewModel : Microsoft.UI.Xaml.Data.INotifyPropertyChanged
{
// Declaring a constructor (or constructors) in the IDL causes the runtime class to be
// activatable from outside the compilation unit.
NodeViewModel();
String Name;
Double X;
Double Y;
}
}
用于创建绑定的 CPP 文件:
void BindingHelperNodes::OnBindingPathPropertyChanged( winrt::Microsoft::UI::Xaml::DependencyObject const& d, winrt::Microsoft::UI::Xaml::DependencyPropertyChangedEventArgs const& e )
{
if(Microsoft::UI::Xaml::Controls::ListBoxItem item{ d.try_as<Microsoft::UI::Xaml::Controls::ListBoxItem>() })
{
Microsoft::UI::Xaml::Data::Binding binding;
binding.Mode( Microsoft::UI::Xaml::Data::BindingMode::OneWay );
Microsoft::UI::Xaml::PropertyPath propertyPath( L"X" );
binding.Path( propertyPath );
// Alternative 1 works
//Microsoft::UI::Xaml::Data::BindingOperations::SetBinding(
// d,
// Microsoft::UI::Xaml::Controls::Canvas::LeftProperty(),
// binding);
// Alternative 2 works, too
item.SetBinding( Microsoft::UI::Xaml::Controls::Canvas::LeftProperty(), binding );
}
}
此致
阿尔弗雷德
我将 Xaml 中的 ListBox
绑定到 NetworkViewModel
实例,该实例包含 NodeViewModel
实例的集合。 NodeViewModel
实例应显示在 canvas 的 X 和 Y 位置,由 NodeViewModel
.
我想绑定 ListBoxItem
的 Canvas。左和Canvas。顶部到 X 和 Y。我假设在 WinUI 中不可能在样式中使用绑定。解决方法可以是一个 helper class,它带有绑定源路径的附加属性。它在助手 属性 的 PropertyChangedCallback
中创建代码隐藏绑定。但是绑定不起作用,为什么?
void BindingHelperNodes::OnBindingPathPropertyChanged( winrt::Microsoft::UI::Xaml::DependencyObject const& d,
winrt::Microsoft::UI::Xaml::DependencyPropertyChangedEventArgs const& e )
{
if(Microsoft::UI::Xaml::Controls::ListBoxItem item{ d.try_as<Microsoft::UI::Xaml::Controls::ListBoxItem>() })
{
Microsoft::UI::Xaml::Controls::Canvas::LeftProperty;
Microsoft::UI::Xaml::Data::Binding binding;
binding.Mode( Microsoft::UI::Xaml::Data::BindingMode::OneWay );
Microsoft::UI::Xaml::PropertyPath propertyPath( L"Y" );
binding.Path( propertyPath );
Microsoft::UI::Xaml::Data::RelativeSource relativeSource;
relativeSource.Mode( Microsoft::UI::Xaml::Data::RelativeSourceMode::Self );
binding.RelativeSource( relativeSource );
Microsoft::UI::Xaml::Data::BindingOperations::SetBinding(
d,
Microsoft::UI::Xaml::Controls::Canvas::LeftProperty(),
binding);
//item.SetBinding( Microsoft::UI::Xaml::Controls::Canvas::LeftProperty(), binding );
}
}
<Grid>
<Grid.Resources>
<ResourceDictionary>
<Style x:Name="listBoxItemContainerStyle2" TargetType="ListBoxItem">
<Setter Property="Canvas.Left" Value="0"/>
</Style>
</ResourceDictionary>
</Grid.Resources>
<ListBox Grid.Row="1" ItemsSource="{x:Bind mainViewModel.NetworkViewModel.Nodes, Mode=OneWay}"
>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="local:BindingHelperNodes.CanvasLeftBindingPath" Value="X"/>
</Style>
</ItemsControl.ItemContainerStyle>
<ListBox.Template>
<ControlTemplate TargetType="ListBox">
<ItemsPresenter />
</ControlTemplate>
</ListBox.Template>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Background="Transparent" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate x:DataType="local:NodeViewModel">
<Grid
Width="120"
Height="60"
>
<!-- This rectangle is the main visual for the node. -->
<Rectangle
Stroke="Black"
Fill="White"
RadiusX="40"
RadiusY="40"
/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
幸运的是我发现了问题!真正的问题是第 13 行中对 SetBinding() 的调用,它没有任何效果。但是我居然忘了在IDL文件中设置属性“[Microsoft.UI.Xaml.Data.Bindable]”!
IDL 文件:
namespace NetworkView
{
[Microsoft.UI.Xaml.Data.Bindable]
runtimeclass NodeViewModel : Microsoft.UI.Xaml.Data.INotifyPropertyChanged
{
// Declaring a constructor (or constructors) in the IDL causes the runtime class to be
// activatable from outside the compilation unit.
NodeViewModel();
String Name;
Double X;
Double Y;
}
}
用于创建绑定的 CPP 文件:
void BindingHelperNodes::OnBindingPathPropertyChanged( winrt::Microsoft::UI::Xaml::DependencyObject const& d, winrt::Microsoft::UI::Xaml::DependencyPropertyChangedEventArgs const& e )
{
if(Microsoft::UI::Xaml::Controls::ListBoxItem item{ d.try_as<Microsoft::UI::Xaml::Controls::ListBoxItem>() })
{
Microsoft::UI::Xaml::Data::Binding binding;
binding.Mode( Microsoft::UI::Xaml::Data::BindingMode::OneWay );
Microsoft::UI::Xaml::PropertyPath propertyPath( L"X" );
binding.Path( propertyPath );
// Alternative 1 works
//Microsoft::UI::Xaml::Data::BindingOperations::SetBinding(
// d,
// Microsoft::UI::Xaml::Controls::Canvas::LeftProperty(),
// binding);
// Alternative 2 works, too
item.SetBinding( Microsoft::UI::Xaml::Controls::Canvas::LeftProperty(), binding );
}
}
此致 阿尔弗雷德