我目前正在处理自定义UserControl的问题,我想将子控件的某些属性公开为父级的属性,我也希望数据绑定成为可能。为了实现这一切,我在父级上创建了附加的DependencyProperties:
//TimeframeSelector.xaml.cs
public static readonly DependencyProperty EnableEndFilterProperty =
DependencyProperty.RegisterAttached(
"EnableEndFilter",
typeof(bool),
typeof(TimeframeSelector),
new FrameworkPropertyMetadata(false,
FrameworkPropertyMetadataOptions.Inherits |
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public static bool GetEnableEndFilter(DependencyObject obj)
{
return (bool)obj.GetValue(EnableEndFilterProperty);
}
public static void SetEnableEndFilter(DependencyObject obj, bool value)
{
obj.SetValue(EnableEndFilterProperty, value);
}
public bool EnableEndFilter
{
get { return (bool)GetValue(EnableEndFilterProperty); }
set { SetValue(EnableEndFilterProperty, value); }
}
这些附加的DP用于该控件的xaml:
//TimeframeSelector.xaml
<UserControl x:Class="EveTrader.Wpf.Controls.TimeframeSelector"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:ctrl="clr-namespace:EveTrader.Wpf.Controls"
mc:Ignorable="d">
<CheckBox IsChecked="{Binding
Path=(ctrl:TimeframeSelector.EnableEndFilter),
RelativeSource={RelativeSource Self}, Mode=TwoWay}"/>
</UserControl>
现在,该控件用于另一个控件:
<ctrl:TimeframeSelector EnableEndFilter="{Binding ApplyEndFilter}" [...]/>
此视图的ViewModel提供了一个来自用户设置的值,该值在控件中正确显示,但控件中所做的任何更改都不会返回到ViewModel。
所以问题是:如何让控件双向工作?有些东西必须工作,否则控件将为空(就像我在DP中添加Inherits标志之前那样)。
答案 0 :(得分:1)
继承的值与Bindings不同。当您为从父级继承的属性设置值时(正如您的TwoWay Binding在写入源时所做的那样),它会覆盖继承的值。继承是11 possible value sources中的第10个。
在这种情况下,使用带继承的附加属性并没有获得任何东西,所以你可以通过使用标准DP来简化你的XAML。
public static readonly DependencyProperty EnableEndFilterProperty =
DependencyProperty.Register(
"EnableEndFilter",
typeof(bool),
typeof(TimeframeSelector),
new FrameworkPropertyMetadata(false,
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
您可以使用ElementName或RelativeSource Binding直接将父UserControl用作绑定源,这将允许Binding在两个方向上工作,如您所愿。
<CheckBox IsChecked="{Binding Path=EnableEndFilter, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ctrl:TimeFrameSelector}}}"/>
IsChecked是TwoWayByDefault,所以你也可以从Binding中省略它。
答案 1 :(得分:0)
尝试将UserControl的XAML更改为:
<UserControl x:Name="uc" ...>
<CheckBox IsChecked="{Binding ElementName=uc, Path=(ctrl:TimeFrameSelector.EnableEndFilter), Mode=TwoWay}"/>
</UserControl>