【问题标题】:Set a ResourceDictionary DataContext from code behind从后面的代码中设置 ResourceDictionary DataContext
【发布时间】:2011-09-28 16:57:03
【问题描述】:

我正在尝试从我的资源字典后面的代码中设置一个 ResourceDictionary DataContext。

我有一个使用自己的样式(资源字典)的数据模板,该样式包含一个具有自己样式的复选框:

<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;
    }

不起作用(当然)。

我想我需要获取 Ancestor(资源字典用户控件)的句柄,但不知道如何执行此操作 - 或者可能有其他方法..

谢谢

【问题讨论】:

  • 你为什么要这样做?发布一些示例代码,是吗?
  • 这没有多大意义。当然,ResourceDictionaries 没有 DataContext,它们在任何方面都不是您不能使用 DataBinding 的控件。 ResourceDictionary 就像名字所说的,只是一个由 Key 标识的资源字典。可能令人困惑的是,UserControl 和 Windows 有一个 XAML 文件,您可能会将这些 XAML 与仅描述 ResourceDictionaries 的 XAML 混在一起。但它们完全不同。 XAML 并不意味着它是 ResourceDictionary。

标签: wpf xaml resourcedictionary


【解决方案1】:

正如@dowhilefor 的评论所说,资源字典只是资源的集合,因此不需要DataContext。但是,您可以将代码隐藏文件添加到 ResourceDictionary,这可能就是您要查找的内容。

在与ResourceDictionary 相同的目录中创建一个新类,并将其命名为 ResourceDictionaryName.xaml.cs。它将成为您的 ResourceDictionary 的代码隐藏文件。

打开新的.cs文件,确保有以下内容(不记得是不是自动添加的):

public partial class ResourceDictionaryName
{
    public ResourceDictionaryName()
    {
        InitializeComponent();
    }
}

接下来,打开您的 XAML 文件并将以下 x:Class 属性添加到 ResourceDictionary 标记:

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

现在你的ResourceDictionary实际上是一个类,并且可以有一个代码隐藏文件。

编辑

为了响应您的编辑,我将使用 CheckBox 本身并获取 CheckBox 的 DataContext,或者遍历可视化树以找到我正在寻找的 UserControl,然后获取它的 Data Context

简单的方法:

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 - 是的,这正是我正在做的事情 - 但是我怎样才能引用父(用户控件的)视图模型? (请参阅修改后的问题。
  • 通常我使用(sender as CheckBox).DataContext 来获取 ViewModel,或者如果 DataContext 不是 ViewModel,我将获取 CheckBox 引用 (sender),然后向上遍历可视化树,直到找到MyUserControl 类型的对象并获取它的 DataContext。查看我的答案的编辑
  • InitializeComponent();在这个方法中没有找到方法。请帮忙。我需要从某个 Control 继承这个类吗?
  • @deathrace 您的 XAML 是否包含 x:Class 属性?如果您遇到问题,最好发布一个新问题,详细说明您的情况。
  • 我有一个新问题,如果该线程中的任何人愿意提供帮助:stackoverflow.com/questions/37018071/…
猜你喜欢
  • 1970-01-01
  • 2021-08-15
  • 1970-01-01
  • 2023-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-20
  • 1970-01-01
相关资源
最近更新 更多