在Dependency属性/ AttachedProperty中更新Normal属性,

时间:2015-08-31 18:33:35

标签: c# wpf xaml binding dependency-properties

我正在尝试绑定AvalonDock的正常属性,

  

的xmlns:xcad = “http://schemas.xceed.com/wpf/xaml/avalondock”

 <xcad:LayoutAnchorable Title="Folder" CanHide="{Binding IsHideExplorerView}">
      <Views:ExplorerView DataContext="{Binding ExplorerViewModel}"/>
 </xcad:LayoutAnchorable>

这里CanHideNormal property,如果尝试绑定会抛出异常,如

  

A 'Binding' can only be set on a DependencyProperty of a DependencyObject.

我的问题是,是否有可能以任何方式使普通属性覆盖DependencyProperty以使其成为Bindable

修改

添加了一个继承LayoutAnchorablePropertyChangedCallback DependencyProperty从不致电的课程。

 public class ExtendedAnchorableItem : LayoutAnchorable
 {
     public static readonly DependencyProperty IsCanHideProperty =
        DependencyProperty.RegisterAttached("IsCanHide", typeof(bool), typeof(ExtendedAnchorableItem),
            new FrameworkPropertyMetadata((bool)false,
                new PropertyChangedCallback(OnCanHideChanged)));
    public bool IsCanHide
    {
        get { return (bool)GetValue(IsCanHideProperty); }
        set { SetValue(IsCanHideProperty, value);

this.IsVisible = value; //无效。

             }
    }
    private static void OnCanHideChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        ((ExtendedAnchorableItem)d).Hide();
    }
  }

XAML

 <xcad:LayoutAnchorablePane>
     <Utility:ExtendedAnchorableItem IsCanHide="{Binding IsHideExplorer}">
         <Views:ExplorerView DataContext="{Binding ExplorerViewModel}"/>
      </Utility:ExtendedAnchorableItem>
 </xcad:LayoutAnchorablePane>

同样,我尝试创建一个AttachedProperty,可以将其挂钩到LayoutAnchorable,但是PropertyChangedCallback永远不会为我发布的新问题调用click here

任何帮助人员?

3 个答案:

答案 0 :(得分:1)

我做过以前的例子在我的情况下我需要创建一个新按钮,其中有两个图像,一个是按钮可用,另一个是当它被禁用时,首先我创建了一个名为&#的新用户控件34;为myButton&#34;我的xaml就像这样

<Button ToolTip="{Binding ButtonLabel,RelativeSource={RelativeSource AncestorType=UserControl,Mode=FindAncestor},UpdateSourceTrigger=PropertyChanged}" 
                Command="{Binding ButtonCommand,RelativeSource={RelativeSource AncestorType=UserControl,Mode=FindAncestor},UpdateSourceTrigger=PropertyChanged}"
                Cursor="Hand" VerticalAlignment="Center" >
            <Button.Template>
                <ControlTemplate>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="45"/>
                            <ColumnDefinition Width="*"/>
                        </Grid.ColumnDefinitions>
                        <Image Name="ButtonImage" IsEnabled="{Binding Path=IsEnabled,RelativeSource={RelativeSource AncestorType=Button,Mode=FindAncestor}}"  >
                            <Image.Style>
                                <Style TargetType="{x:Type Image}">
                                    <Style.Triggers>
                                        <Trigger Property="IsEnabled" Value="True">
                                            <Setter Property="Source" Value="{Binding ActiveImage,RelativeSource={RelativeSource AncestorType=UserControl,Mode=FindAncestor},UpdateSourceTrigger=PropertyChanged}"/>
                                        </Trigger>
                                        <Trigger Property="IsEnabled" Value="False">
                                            <Setter Property="Source" Value="{Binding DeactiveImage,RelativeSource={RelativeSource AncestorType=UserControl,Mode=FindAncestor},UpdateSourceTrigger=PropertyChanged}"/>
                                        </Trigger>
                                    </Style.Triggers>
                                </Style>
                            </Image.Style>
                        </Image>
                        <Label Name="LabelContent" Content="{Binding ButtonLabel,RelativeSource={RelativeSource AncestorType=UserControl,Mode=FindAncestor},UpdateSourceTrigger=PropertyChanged}" 
                       Grid.Column="1" IsEnabled="{Binding Path=IsEnabled,RelativeSource={RelativeSource AncestorType=Button,Mode=FindAncestor}}" VerticalContentAlignment="Center"  />
                    </Grid>
                </ControlTemplate>
            </Button.Template>
        </Button> 

然后我使用此代码添加了ActiveImage和DeactiveImage的依赖项属性

public static  DependencyProperty activeImage =
           DependencyProperty.Register("ActiveImage", typeof(type of this property like  "string"), typeof(type of the custom control that you need like  "MyButton"), new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

        public string ActiveImage
        {
            get { return (string)GetValue(activeImage); }
            set { SetValue(activeImage, value); }
        }

然后我在我的项目中使用了这个新控件

<custom:MyButton ButtonCommand="{Binding DecreaseImagesCount}" ButtonLabel="ZoomIn" ActiveImage="/Images/ActiveImages/ZoomIn.png" DeactiveImage="/Images/GrayImages/ZoomIn.png" 
                                             Grid.Column="2" Margin="3,4" />

注意我现在可以绑定Button Image的路径

答案 1 :(得分:1)

如果仅从视图模型中设置该属性就足够了,那么您可以使用附加行为。 只需创建一个新类并添加一个这样的附加属性(我没有真正测试过这个,因为我实际上没有AvalonDock,但你应该明白这一点):

public class YourBehavior
{
    public static readonly DependencyProperty YourCanHideProperty = DependencyProperty.RegisterAttached(
                "YourCanHide",
                typeof(bool),
                typeof(LayoutAnchorable),
                new PropertyMetadata(YourCanHidePropertyChanged));

    private static void YourCanHidePropertyChanged(
        DependencyObject dependencyObject,
        DependencyPropertyChangedEventArgs e)
    {
        LayoutAnchorable control = dependencyObject as LayoutAnchorable;
        if (control != null)
        {
            control.CanHide = e.NewValue as bool;
        }
    }

    public static bool GetYourCanHideProperty(LayoutAnchorablewindow)
    {
        return window.GetValue(YourProperty) as bool?;
    }

    public static void SetYourCanHideProperty(LayoutAnchorable control, bool value)
    {
        window.SetValue(YourProperty, value);
    }
}

现在你应该能够像这样使用这种行为:

<xcad:LayoutAnchorable Title="Folder" namespacealias:YourBehavior.YourCanHideProperty="{Binding IsHideExplorerView}"/>

如果您想让它在两个方向都有效,请查看附加的混合行为。

答案 2 :(得分:0)

是的,你可以这样做..你需要实现INotifypropertyChanged接口并在属性setter中引发一个ProprtyChanged事件。将属性更改为DependencyProperty后,您将获得通知机制,因此属性更改将传播到目标(在本例中为xcad)。

你可以找到很多实现INotifyPropertyChanged的例子。