将一个控件绑定到另一个控件的DataContext

3

我使用DataContext将我的WPF窗口绑定到应用程序层类(WindowVM.cs),并将其放置在Window.xaml.cs构造函数中(DataContext = WindowVM)。但是,我想将一个控件(btnAdd)绑定到Window.xaml.cs属性。因此,在Window.xaml.cs构造函数中,我添加了this.btnAdd.DataContext。这是Window.xaml.cs构造函数和我想要绑定Button btnAdd的属性:

    public Window()
    {
        InitializeComponent();
        DataContext = WindowVM;
        this.btnAdd.DataContext = this;
    }

    public RelayCommand Add
    {
        get
        {
            return _add == null ? _add= new RelayCommand(AddPP, CanAddPP) : _add;
        }
        set
        {
            OnPropertyChanged("Add");
        }
    }

Xaml长成这个样子(类PP是WindowVM属性):

<TextBox Name="txtName" Text="{Binding PP.Name, ValidatesOnDataErrors=true, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Name="txtSurname" Text="{Binding PP.Surname, ValidatesOnDataErrors=true, UpdateSourceTrigger=PropertyChanged}" />
<Button Command="{Binding Add}" Content="Add" ... />

一切正常,但控制台输出如下:

BindingExpression path error: 'Add' property not found on 'object' ''WindowVM'...

下一次调用 Add 属性时不会出现任何控制台输出错误。

现在我有点困惑这个错误是因为第一个 DataContext(给 WindowVM)导致的,因为没有 Add 属性,但是通过 this.btnAdd.DataContext 这一行代码,Add 属性被找到并且这就是它正常工作的原因吗?


那么如果您不打算将命令放在ViewModel中,为什么要使用MVVM(或类似的模式)呢?ViewModel应该是命令所在的地方。Window的代码后台实际上不应该有任何代码。 - Ryan Alford
我将命令放在ViewModel中,但是遇到了问题,因为我需要关闭窗口。这个绑定可以工作:{Binding ElementName=MyUsersView, Path=Add}。但是,我会尝试使用这个链接中的方法:http://blog.excastle.com/2010/07/25/mvvm-and-dialogresult-with-no-code-behind/,然后将命令放在ViewModel中。 - davor
3个回答

2

只需使用RelativeSource在XAML中设置ButtonDataContext:

<Button Command="{Binding Add}" Content="Add" DataContext="{Binding Add, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" />

1
我曾遇到过这个问题,虽然这是一篇比较旧的帖子,但我认为这可能会对未来遇到此问题的人有所帮助。
我的做法是将视图模型声明为资源。
<Page.Resources>
    <local:LocationListViewModel x:Key="LocationList" />
    <local:LocationNewViewModel x:Key="NewLocation" />
    <code:BinaryImageConverter x:Key="imgConverter" />
</Page.Resources>

然后,我想要与特定视图模型相关联的任何控件,我都将其添加到它们的数据上下文中。

<TabItem x:Name="tabSettingsLocations" x:Uid="tabSettingsLocations" 
                 Header="Locations"
                 DataContext="{StaticResource ResourceKey=LocationList}">....

<TabItem x:Name="tbSettingsLocationsAdd" x:Uid="tbSettingsLocationsAdd" 
         Header="Add New"
         DataContext="{StaticResource ResourceKey=NewLocation}">....

<Image x:Name="imgSettingsLocationMapNew" x:Uid="imgSettingsLocationMapNew" 
         Source="{Binding Map, Converter={StaticResource imgConverter}, 
         Mode=TwoWay}"
         DataContext="{StaticResource ResourceKey=NewLocation}" />

在我的示例中,我将Listview绑定到列表视图模型,并为我的新条目创建了一个新的单个位置。您会注意到,通过将其创建为资源,我可以将tabitem和图像(不是tabitem的子项)绑定到新位置视图模型。
我的添加新位置的命令在新位置视图模型中。
<TabItem x:Name="tbSettingsLocationsAdd" x:Uid="tbSettingsLocationsAdd" 
         Header="Add New"
         DataContext="{StaticResource ResourceKey=NewLocation}">....

    <Button x:Name="btnSettingsLocationSaveAdd" x:Uid="btnSettingsLocationSaveAdd" Content="Submit" Margin="0,80,10,0" 
        VerticalAlignment="Top" Style="{DynamicResource ButtonStyle}" HorizontalAlignment="Right" Width="75"
        Command="{Binding AddCommand}" />.....

这是我绑定到新位置视图模型的选项卡项的子项。

希望这可以帮助你。


0
当您设置DataContext属性时,窗口会重置其子控件的绑定。即使是按钮的绑定也会被重置。 在此时(在“button.DataContext = this”被评估之前),将在WindowVM中搜索“Add”。然后,您将窗口类设置为按钮的DC,一切都正常工作。
为避免最初的错误,请交换这两行代码。
public Window()
{
    InitializeComponent();
    DataContext = WindowVM;
    this.btnAdd.DataContext = this;
}

转换成这个

public Window()
{
    InitializeComponent();
    this.btnAdd.DataContext = this;
    DataContext = WindowVM;
}

现在我该如何为这个按钮设置按键绑定?<KeyBinding Command="{Binding SaveCommand}" Key="F8" />无法工作。 - davor
你的KeyBinding看起来不错,但你仍然需要使用CommandBinding来捕获它。 <Window.CommandBindings> <CommandBinding Command={Binding SaveCommand} Executed="CommandExecuted_Handler" /> </Window.CommandBindings> 其中“CommandExecuted_Handler”是它的事件处理程序。 你可以在这里找到文档:http://msdn.microsoft.com/de-de/library/system.windows.input.commandbinding.executed.aspx - NikoR

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接