简体   繁体   English

CommandParameter上的DataContext与Command本身上的DataContext不同

[英]DataContext on CommandParameter differs from DataContext on Command itself

This question is related to my previous question here: Predicate won't validate parameter correctly 这个问题与我之前的问题有关: Predicate不会正确验证参数

At first some information on my Models: 首先是关于我的模型的一些信息:

BaseViewModel: BaseViewModel:

public abstract class BaseViewModel : INotifyPropertyChanged 
{
    public event PropertyChangedEventHandler PropertyChanged;

    private string _name;
    public string Name
    {
        get 
        {
            return _name;
        }
        set 
        {
            if (Name != value) 
            {
                _name = value;
                OnPropertyChanged("Name");
            }
        }
    }

    private BaseViewModel _homePage;
    public BaseViewModel HomePage 
    {
        get 
        {
            return _homePage;
        }
        set 
        {
            if (HomePage != value) 
            {
                _homePage = value;
                OnPropertyChanged("HomePage");
            }
        }
    }

    public void OnPropertyChanged(string propertyName) 
    {
        PropertyChangedEventHandler temp = PropertyChanged;
        if (temp != null) 
        {
            temp(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Problem: 问题:

<Button Content="{Binding Name}" Command="{Binding DataContext.ChangePageCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
        CommandParameter="{Binding HomePage}"/>

As you can see in the BaseViewModel, the Properties "Name" and "HomePage" are defined in the same class so they should be accessible if the DataContext is a ViewModel which derives from "BaseViewModel". 正如你在BaseViewModel中看到的那样,属性“Name”和“HomePage”在同一个类中定义,因此如果DataContext是一个派生自“BaseViewModel”的ViewModel,它们应该是可访问的。 At first I lost my mind because nothing seemed to work - the output window said that the value of "HomePage" could not be retrieved - other that the Name which got bound properly every time. 起初我失去了理智,因为似乎没有任何工作 - 输出窗口表示无法检索“HomePage”的值 - 除了每次都正确绑定的Name。

After I nearly gave up I named my View "Test" and tried to redirect the CommandProperty binding along an ElementName - and it worked: 在我几乎放弃之后,我命名了我的View“Test”并试图沿着ElementName重定向CommandProperty绑定 - 它工作正常:

<Button Content="{Binding Name}" Command="{Binding DataContext.ChangePageCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
        CommandParameter="{Binding DataContext.HomePage, ElementName=Test}"/>

But why? 但为什么? Why differs the DataContext between the Name Property which could be bound without assigning an ElementName and HomePage which requires the ElementName? 为什么在Name属性之间区分DataContext而不分配ElementName和HomePage需要ElementName?

Update 1: 更新1:

MainViewModel : BaseViewModel MainViewModel:BaseViewModel

private RelayCommand _command;
    public RelayCommand ChangePageCommand {
        get {
            return _command ?? (_command = new RelayCommand(p => ChangeViewModel((BaseViewModel)p), x => {
                return x is BaseViewModel;
            }));
        }
    }

public void ChangeViewModel(BaseViewModel viewModel) {
        CurrentPageViewModel = viewModel;
    }

Update 2: 更新2:

<Window.Resources>
    <DataTemplate DataType="{x:Type home:HomeViewModel}">
        <home:Home/>
    </DataTemplate>
    <DataTemplate DataType="{x:Type ua:UserAdministrationViewModel}">
        <ua:UserAdministration/>
    </DataTemplate>
</Window.Resources>
<ContentControl Content="{Binding CurrentPageViewModel}"/>

Update 3: 更新3:

Now it's getting really strange - I tried to add an TextBlock and bind it directly to HomePage.Text - and it works. 现在它变得非常奇怪 - 我试图添加一个TextBlock并将其直接绑定到HomePage.Text - 它的工作原理。

<Button Height="50" Content="{Binding Name}" Command="{Binding DataContext.ChangePageCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
        CommandParameter="{Binding DataContext.HomePage, ElementName=Test}"/>
        <TextBlock Text="{Binding HomePage.Name}"/>

So why can't I directly access HomePage when binding to the CommandParameter but binding a TextBlock's Text Property directly to HomePage.Name works? 那么为什么我不能直接访问HomePage绑定到CommandParameter但将TextBlock的Text属性直接绑定到HomePage.Name有效?

Update 4: 更新4:

The Output Windows sais: 输出Windows sais:

System.Windows.Data Information: 10 : Cannot retrieve value using the binding and no valid fallback value exists; System.Windows.Data信息:10:无法使用绑定检索值,并且不存在有效的回退值; using default instead. 使用默认值。 BindingExpression:Path=Name; BindingExpression:路径=名称; DataItem=null; 的DataItem = NULL; target element is 'Button' (Name=''); target元素是'Button'(Name =''); target property is 'Content' (type 'Object') target属性是'Content'(类型'Object')

System.Windows.Data Information: 10 : Cannot retrieve value using the binding and no valid fallback value exists; System.Windows.Data信息:10:无法使用绑定检索值,并且不存在有效的回退值; using default instead. 使用默认值。 BindingExpression:Path=DataContext.ChangePageCommand; BindingExpression:路径= DataContext.ChangePageCommand; DataItem=null; 的DataItem = NULL; target element is 'Button' (Name=''); target元素是'Button'(Name =''); target property is 'Command' (type 'ICommand') target属性是'Command'(类型'ICommand')

System.Windows.Data Information: 10 : Cannot retrieve value using the binding and no valid fallback value exists; System.Windows.Data信息:10:无法使用绑定检索值,并且不存在有效的回退值; using default instead. 使用默认值。 BindingExpression:Path=HomePage; BindingExpression:路径=首页; DataItem=null; 的DataItem = NULL; target element is 'Button' (Name=''); target元素是'Button'(Name =''); target property is 'CommandParameter' (type 'Object') target属性是'CommandParameter'(类型'Object')

System.Windows.Data Information: 10 : Cannot retrieve value using the binding and no valid fallback value exists; System.Windows.Data信息:10:无法使用绑定检索值,并且不存在有效的回退值; using default instead. 使用默认值。 BindingExpression:Path=HomePage.Name; BindingExpression:路径= HomePage.Name; DataItem=null; 的DataItem = NULL; target element is 'TextBlock' (Name=''); target元素是'TextBlock'(Name =''); target property is 'Text' (type 'String') target属性是'Text'(类型'String')

But everything except the CommandParameter gets bound successfully. 但是除CommandParameter之外的所有内容都会成功绑定。 Is it possible that the CommandParameter (and the underlaying CanExecute-Method) won't get re-validated once the binding is refreshed? 修复绑定后,CommandParameter(和底层的CanExecute-Method)是否可能无法重新验证? Maybe the binding fails at first but every binding except the CommandParameter gets refreshed and revalidated. 也许最初绑定失败但除了CommandParameter之外的每个绑定都会刷新并重新生成。 But how could I solve this issue? 但是我怎么能解决这个问题呢?

I'm proud to announce that I've solved this silly problem: 我很自豪地宣布我已经解决了这个愚蠢的问题:

I assume that the RelativeSource I'm using to redirect my CommandBinding to the Window's ViewModel breaks the DataContext of all following Properties (!Not Controls). 我假设我用来将我的CommandBinding重定向到Window的ViewModel的RelativeSource打破了以下所有属性的DataContext(!Not Controls)。

Not working: 不工作:

<Button Grid.Row="0" 
            Grid.Column="0" 
            Height="50" 
            Content="{Binding PreviousPageViewModel.Name}"
            Command="{Binding DataContext.ChangePageCommand, RelativeSource={RelativeSource AncestorType=Window}}"
            CommandParameter="{Binding PreviousPageViewModel}" />

Working: 工作:

<Button Grid.Row="0" 
            Grid.Column="0" 
            Height="50" 
            Content="{Binding PreviousPageViewModel.Name}" 
            CommandParameter="{Binding PreviousPageViewModel}" 
            Command="{Binding DataContext.ChangePageCommand, RelativeSource={RelativeSource AncestorType=Window}}"/>

So in this case the order of Properties is important. 所以在这种情况下,属性的顺序很重要。

Note: The DataContext for all following Controls is correct. 注意:所有后续控件的DataContext都是正确的。

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

相关问题 WPF - window 的数据上下文中的命令和来自用户控件中的列表视图的命令参数 - WPF - Command in datacontext of the window and commandparameter from listview in user control 在CommandParameter中传递项DataContext - Pass the item DataContext in CommandParameter DataContext为ViewModel时将CommandParameter绑定到本地项 - Bind CommandParameter to local item while DataContext is ViewModel 在 Windows 10 中将 Datacontext 作为 CommandParameter 传递给 Viewmodel - Passing Datacontext as CommandParameter to Viewmodel in Windows 10 C#-将CommandParameter绑定到ListViewItem的“ DataContext” - C# - Bind CommandParameter to the “DataContext” of a ListViewItem 从View直接调用ViewModel。 可以自行更改DataContext吗? - Direct calls from View to ViewModel. Can DataContext be changed on itself? 如何通过DataContext类公开DataContext? - How to expose the DataContext from with-in a DataContext class? 从另一个数据上下文加载数据上下文实体 - Load datacontext entities from another datacontext WPF数据绑定ContextMenuItem的CommandParameter到TreeViewItem的DataContext - WPF Databinding ContextMenuItem's CommandParameter to TreeViewItem's DataContext 从资源绑定到数据上下文 - Binding to datacontext from Resources
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM