从代码后台设置ResourceDictionary的DataContext

3

我正在尝试从我的Resource Dictionary的代码后台设置ResourceDictionary DataContext。

我有一个使用自己样式(Resource Dictionary)的Data Template,样式包含一个带有自己样式的复选框:

<Style x:Key="CheckBoxStyle" TargetType="CheckBox">
    <EventSetter Event="CheckBox.Checked" Handler="CheckBox_Checked"/>
    <EventSetter Event="CheckBox.Unchecked" Handler="CheckBox_Unchecked"/>        
</Style>

在 CheckBox_Checked 事件中,我想要引用字典的父级(一个用户控件)视图模型来执行一个函数,但由于资源字典没有 DataContext 属性设置 DataContext,因此无法从控件事件内部设置。例如:

    private void CheckBox_Checked(object sender, RoutedEventArgs e)
    {  
      MyViewModel viewModel = (MyViewModel)DataContext;
    }

当然不起作用。

我认为我需要获取祖先(资源字典用户控件)的句柄,但不知道如何做到这一点 - 或者可能有其他方法。

谢谢。


1
你为什么要这样做?能否贴一些示例代码呢? - Jake Berger
1
这并没有太多意义。当然,ResourceDictionaries没有DataContext,它们不是控件,您不能使用DataBinding。 ResourceDictionary就像名称所示,只是由Key标识的资源字典。可能令人困惑的是,UserControl和Windows有一个XAML文件,您可能会将这些XAML与仅描述ResourceDictionaries的XAML混淆。但它们非常不同。 XAML并不意味着它是ResourceDictionary。 - dowhilefor
1个回答

7
如@dowhilefor的评论所说,资源字典只是一组资源,因此不需要DataContext。但是,您可以向ResourceDictionary添加一个代码后备文件,这可能是您要寻找的内容。
在与您的ResourceDictionary相同的目录中创建一个新类,并将其命名为ResourceDictionaryName.xaml.cs。它将成为您的ResourceDictionary的代码后备文件。
打开新的.cs文件,并确保以下内容存在(无法记住是否自动添加):
public partial class ResourceDictionaryName
{
    public ResourceDictionaryName()
    {
        InitializeComponent();
    }
}

接下来,打开你的XAML文件,在ResourceDictionary标签上添加以下x:Class属性:

<ResourceDictionary x:Class="MyNamespace.ResourceDictionaryName" ... />

现在你的ResourceDictionary实际上是一个类,可以有一个代码后台文件。
编辑:
针对您的编辑,我会使用复选框本身并获取复选框的数据上下文,或者向上遍历可视树以找到我要查找的用户控件,然后获取它的数据上下文。
简单的方法:
private void CheckBox_Checked(object sender, RoutedEventArgs e)
{  
    var cbx = sender as CheckBox;
    MyViewModel viewModel = (MyViewModel)cbx.DataContext;
}

如果 CheckBox 的 DataContext 不是你要查找的 ViewModel:

private void CheckBox_Checked(object sender, RoutedEventArgs e)
{  
    var cbx = sender as CheckBox;
    var userControl = FindAncestor<MyUserControl>(cbx);
    MyViewModel viewModel = (MyViewModel)myUserControl.DataContext;
}

public static T FindAncestor<T>(DependencyObject current)
    where T : DependencyObject
{
    current = VisualTreeHelper.GetParent(current);

    while (current != null)
    {
        if (current is T)
        {
            return (T)current;
        }
        current = VisualTreeHelper.GetParent(current);
    };
    return null;
}

谢谢Rachel - 是的,那正是我正在做的事情 - 但是我该如何引用父级(用户控件的)视图模型呢?(请参见修改后的问题。) - Joe.Net
通常我使用(sender as CheckBox).DataContext来获取ViewModel,或者如果DataContext不是ViewModel,我会获取CheckBox引用(sender),然后遍历可视树直到找到类型为MyUserControl的对象并获取它的DataContext。请参见我的答案编辑。 - Rachel
在这种方法中找不到InitializeComponent();方法。请帮忙。我需要从某个控件继承这个类吗? - deathrace
@deathrace дҪ зҡ„XAMLж–Ү件дёӯжҳҜеҗҰеҢ…еҗ«x:ClassеұһжҖ§пјҹеҰӮжһңдҪ йҒҮеҲ°дәҶй—®йўҳпјҢжңҖеҘҪжҳҜеҸ‘еёғдёҖдёӘж–°зҡ„й—®йўҳ并жҸҗдҫӣиҜҰз»Ҷжғ…еҶөгҖӮ - Rachel
我有一个新问题,如果这个线程中的任何人愿意帮忙:http://stackoverflow.com/questions/37018071/wpf-binding-resourcedictionary-source-to-a-resourcedictionary-property-of-the-presenter-or-datacontext - turkinator

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