附加的依赖属性不会在所有方向上绑定

时间:2010-09-14 21:54:51

标签: c# .net wpf

我目前正在处理自定义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标志之前那样)。

2 个答案:

答案 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>
相关问题