'code behind' 中设置的 WPF 控件属性,之后绑定将被忽略
WPF control properties set in 'code behind', after that binding is ignored
我真的是 WPF 新手。我试图在代码中为 control-属性 设置默认值,并希望在数据上下文 (VM) 可用时通过数据绑定覆盖 属性。但是数据绑定在这种情况下不起作用。
示例:
隐藏代码:
public partial class MyViewControl : UserControl
{
public MyViewControl()
{
InitializeComponent();
// it works if I remove this line
panelControl.Visibility = Visibility.Hidden;
}
}
xaml 用户控件:
<DockPanel Name="panelControl" Visibility="{Binding
MyViewModelProperty_IsVisible_ConvertedToVisibility}">
xaml 主窗口:
<my:MyViewControl DataContext="{Binding ElementName=lbListBox,
Path=SelectedItem}"/>
其实FallbackValue这个参数对这个场景有效,但是我想知道技术原因,为什么控件属性在代码设置后无法绑定?
Xaml 在 InitializeComponent()
期间被处理,所以这是正在发生的事情:
InitializeComponent(); // binding is set
panelControl.Visibility = Visibility.Hidden; // binding is removed (value is set)
您可以恢复绑定
InitializeComponent();
panelControl.Visibility = Visibility.Hidden;
BindingOperations.SetBinding(panelControl, Control.VisibilityProperty,
new Binding()
{
Path = new PropertyPath(nameof(ViewModel.MyViewModelProperty_IsVisible_ConvertedToVisibility)),
Source = viewModelInstance, // this.DataContext ?
});
之后它会起作用。但是还不是很清楚为什么要首先覆盖绑定。
在代码中更改绑定 属性 值时防止绑定被清除的一种简单方法是使用 TwoWay
绑定模式:
<DockPanel Name="panelControl"
Visibility="{Binding MyViewModelProperty_IsVisible_ConvertedToVisibility,
Mode=TwoWay}">
当然,我很难找到这个,哈哈。
实际上,如果您有理由直接修改控件的 属性(而不是修改绑定的 属性),那么使用 TwoWay
模式确实有意义 - 您会想要绑定 属性 也反映了变化。
顺便说一下,与其绑定到 Visibility
类型的 属性,不如使用绑定到布尔值并使用像 BooleanToVisibilityConverter
这样的转换器,因为它解耦了 ViewModel 来自 View 甚至更好:
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</Window.Resources>
...
<DockPanel Name="panelControl"
Visibility="{Binding MyViewModelProperty_IsVisible,
Converter={StaticResource BooleanToVisibilityConverter},
Mode=TwoWay}">
是的,我知道这是一个老问题并且有一个公认的答案,但我没有找到直接提供此解决方案的其他答案。
我真的是 WPF 新手。我试图在代码中为 control-属性 设置默认值,并希望在数据上下文 (VM) 可用时通过数据绑定覆盖 属性。但是数据绑定在这种情况下不起作用。
示例:
隐藏代码:
public partial class MyViewControl : UserControl { public MyViewControl() { InitializeComponent(); // it works if I remove this line panelControl.Visibility = Visibility.Hidden; } }
xaml 用户控件:
<DockPanel Name="panelControl" Visibility="{Binding
MyViewModelProperty_IsVisible_ConvertedToVisibility}">
xaml 主窗口:
<my:MyViewControl DataContext="{Binding ElementName=lbListBox,
Path=SelectedItem}"/>
其实FallbackValue这个参数对这个场景有效,但是我想知道技术原因,为什么控件属性在代码设置后无法绑定?
Xaml 在 InitializeComponent()
期间被处理,所以这是正在发生的事情:
InitializeComponent(); // binding is set
panelControl.Visibility = Visibility.Hidden; // binding is removed (value is set)
您可以恢复绑定
InitializeComponent();
panelControl.Visibility = Visibility.Hidden;
BindingOperations.SetBinding(panelControl, Control.VisibilityProperty,
new Binding()
{
Path = new PropertyPath(nameof(ViewModel.MyViewModelProperty_IsVisible_ConvertedToVisibility)),
Source = viewModelInstance, // this.DataContext ?
});
之后它会起作用。但是还不是很清楚为什么要首先覆盖绑定。
在代码中更改绑定 属性 值时防止绑定被清除的一种简单方法是使用 TwoWay
绑定模式:
<DockPanel Name="panelControl"
Visibility="{Binding MyViewModelProperty_IsVisible_ConvertedToVisibility,
Mode=TwoWay}">
当然,我很难找到这个,哈哈。
实际上,如果您有理由直接修改控件的 属性(而不是修改绑定的 属性),那么使用 TwoWay
模式确实有意义 - 您会想要绑定 属性 也反映了变化。
顺便说一下,与其绑定到 Visibility
类型的 属性,不如使用绑定到布尔值并使用像 BooleanToVisibilityConverter
这样的转换器,因为它解耦了 ViewModel 来自 View 甚至更好:
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</Window.Resources>
...
<DockPanel Name="panelControl"
Visibility="{Binding MyViewModelProperty_IsVisible,
Converter={StaticResource BooleanToVisibilityConverter},
Mode=TwoWay}">
是的,我知道这是一个老问题并且有一个公认的答案,但我没有找到直接提供此解决方案的其他答案。