繁体   English   中英

绑定到依赖属性,而依赖属性又绑定到另一个绑定源

[英]Binding to Dependency Property which is, in turn, bound to another binding source

这很难解释,但我会尽我所能。 我希望有一个可重复使用的控件,它有3个按钮,一个用于创建实体,另一个用于编辑,另一个用于删除,这里是相关部分的缩写XAML。

-

<!-- ActionButtons.xaml -->

<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Top">
        <Button Name="btnNew" Content="New" Command="{Binding Path=NewCommand}" />
        <Button Name="btnEdit" Content="Edit" Command="{Binding Path=EditCommand, Mode=OneWay}" />
        <Button Name="btnDelete" Content="Delete" Command="{Binding Path=DeleteCommand, Mode=OneWay}" />
    </StackPanel>

-

然后,在后面的代码中我有dpprops声明:

// ActionButtons.xaml.cs

public uscActionButtons()
{
            InitializeComponent();
            this.DataContext = this;
        }

        public ICommand NewCommand
        {
            get { return (ICommand)GetValue(NewCommandProperty); }
            set { SetValue(NewCommandProperty, value); }
        }

        // Using a DependencyProperty as the backing store for NewCommand.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty NewCommandProperty =
            DependencyProperty.Register("NewCommand", typeof(ICommand), typeof(uscActionButtons), new UIPropertyMetadata(null, new PropertyChangedCallback(OnCommandChanged)));

我想将NewCommand属性绑定到另一个控件中的特定实现。 样本用途:

<!-- SomeControl.xaml -->
<common:uscActionButtons Grid.Row="0" HorizontalAlignment="Left" 
                                 NewCommand="{Binding NewItemCommand}"
                                 />

// SomeControlViewModel.cs
// Note: SomeControlViewModel IS in the DataContext of SomeControl.
public ICommand NewItemCommand
        {
            get
            {
                if (mNewItemCommand == null)
                {
                    mNewItemCommand = new RelayCommand(x => this.CreateItem());
                }

                return mNewItemGroupCommand;
            }
        }

问题是可重用控件(ActionButtons)没有看到NewItemCommand。 如果我使用一个简单的按钮,它看起来很好。 似乎问题是这种“链式”绑定。 但我知道这是可能的,WPF按钮有一个Command依赖属性,你可以绑定你的命令,所以创建我自己的可重用控件暴露ICommand依赖属性一定不是那么难。

有任何想法吗?

谢谢


编辑:这是解决方案,我所要做的就是将FindSource与FindAncestor一起使用。

<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Top">
        <Button Name="btnNew" Content="New" Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=my:uscActionButtons}, Path=NewCommand, Mode=OneWay}" />
        <Button Name="btnEdit" Content="Edit" Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=my:uscActionButtons}, Path=EditCommand, Mode=OneWay}" />
        <Button Name="btnDelete" Content="Delete" Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=my:uscActionButtons}, Path=DeleteCommand, Mode=OneWay}" />
    </StackPanel>

您看到的问题是您正在改变ActionButtons控件的DataContext 在构造函数中设置其DataContext时,您在其上指定的所有Bindings (甚至来自实例化它的外部XAML)都将指向新的DataContext 因此,当您在SomeControl中应用Binding时,Binding正在尝试绑定DataContext ,这恰好是ActionButtons实例。

我不认为Control应该设置自己的DataContext ,因为它会导致你看到的错误。 如果你想使用UserControl (我可能会自己使用Control以便我可以做TemplateBindings ),那么你可以使用RelativeSource绑定(正如你在Snowbear的评论中提到的那样),并且Bindings应该可以工作。

这是我的代码中缺少的内容:

<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Top">
        <Button Name="btnNew" Content="New" Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=my:uscActionButtons}, Path=NewCommand, Mode=OneWay}" />
        <Button Name="btnEdit" Content="Edit" Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=my:uscActionButtons}, Path=EditCommand, Mode=OneWay}" />
        <Button Name="btnDelete" Content="Delete" Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=my:uscActionButtons}, Path=DeleteCommand, Mode=OneWay}" />
    </StackPanel>

我不得不将FindSource与FindAncestor一起使用。

谢谢你的所有答案!

this.DataContext = this;

这似乎是个问题,因为在这个XAML中:

 NewCommand="{Binding NewItemCommand}"

你绑定到ActionButtons本身的NewItemCommand。 这就是为什么在我看来设置内部控件的自我DataContext是坏模式的原因。 如果你确实需要这个DataContext(你),那么将它设置为顶层内部元素(在你的情况下为StackPanel)

Visual Studio调试器也可以帮助您调试绑定。 如果您将运行带有调试器的应用程序,那么在Visual Studio的输出窗口中您将看到绑定错误并且它们通常很容易理解,错误会让您知道对于此特定绑定,它在ActionButtons实例中查找NewItemCommand属性而不是你期待的课程。

更新在VS中测试您的代码。 输出窗口中出错:

System.Windows.Data Error: 40 : BindingExpression path error: 'NewItemCommand' property not found on 'object' ''uscActionButtons' (Name='')'. BindingExpression:Path=NewItemCommand; DataItem='uscActionButtons' (Name=''); target element is 'uscActionButtons' (Name=''); target property is 'NewCommand' (type 'ICommand')
System.Windows.Data Error: 40 : BindingExpression path error: 'EditCommand' property not found on 'object' ''uscActionButtons' (Name='')'. BindingExpression:Path=EditCommand; DataItem='uscActionButtons' (Name=''); target element is 'Button' (Name='btnEdit'); target property is 'Command' (type 'ICommand')
System.Windows.Data Error: 40 : BindingExpression path error: 'DeleteCommand' property not found on 'object' ''uscActionButtons' (Name='')'. BindingExpression:Path=DeleteCommand; DataItem='uscActionButtons' (Name=''); target element is 'Button' (Name='btnDelete'); target property is 'Command' (type 'ICommand')

您是否可以错过这些错误,例如因为打开输出窗口太晚了?

更新2:

修复与替换你的:

this.DataContext = this;

和我的:

root.DataContext = this; //root - name for stackpanel

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM