如何向DataContext传递参数?

3

是否可以通过XAML将某些数据传递给绑定源/数据上下文?

在我的特定情况下,我希望绑定源被给予创建它的窗口的引用。

例如:

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:MyNamespace"
    x:Name="MyWindow">

    <Window.Resources>
        <local:MarginDataContext x:Key="MyDC"/>
    </Window.Resources>

    <!-- I want to pass in "MyWindow" to "MyDC" here... -->
    <Grid Margin="{Binding Source={StaticResource MyDC}, Path=My_Margin}" /> 
</Window>

注意:MarginDataContext是我自己创建的,因此如果涉及添加构造函数参数之类的操作,那将很好!
更新:我希望解决方案符合项目的某些要求:
  • 不使用x:Reference扩展。
  • 尽可能少地使用代码 (我希望能在XAML中完成大部分工作)。
谢谢!
2个回答

2
我能想到两种方法来做这件事,1)使用MarginDataContext构造函数的参数,2)在代码后台使用DataContextChanged。
方法1:带参数的MarginDataContext 有关更多信息,请参见MSDN上的x:Arguments Directivex:Reference
public class MarginDataContext
{
    public WindowInstance { get; set; }
    ...
}

<!-- xaml -->
<Window.Resources>
    <local:MarginDataContext
        x:Key="MyDC"
        WindowInstance="{x:Reference MyWindow}" />
    <!-- or possibly (not sure about this) -->
    <local:MarginDataContext
        x:Key="MyDC"
        WindowInstance="{Binding ElementName=MyWindow}" />
    <!-- or even (again, not sure about this) -->
    <local:MarginDataContext
        x:Key="MyDC"
        WindowInstance="{Binding RelativeSource={RelativeSource Self}}" />
</Window.Resources>

方法2:使用代码后台。更多信息请参见DataContextChanged
public class MyWindow : Window
{
    ...
    public MyWindow()
    {
        // Attach event handler
        this.DataContextChanged += HandleDataContextChanged;

        // You may have to directly call the Handler as sometimes
        // DataContextChanged isn't raised on new windows, but only
        // when the DataContext actually changes.
    }

    void HandleDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        var dc = DataContext as MarginDataContext;
        if (dc != null)
        {
            // Assuming there is a 'MyWindow' property on MarginDataContext
            dc.MyWindow = this;
        }
    }
}

谢谢Ryan!BlueM的答案对我的需求非常有效,所以我实际上没有尝试这些东西。可能会在某个时候回来尝试,并在此发布结果。再次感谢! - Goose
啊,我看到BlueM的答案和#1是等价的,只是他有正确的语法。 :) - Ryan
我没有尝试过这个,但是我想到了另一种可能性,而不使用x:Reference。请尝试在#1中使用{Binding},看看它是否有效。 - Ryan

2

您可以在XAML中访问MarginDataContext的任何属性。假设您创建了一个WindowInstance属性,那么您可以使用x:Reference在MarginDataContext构造时简单地进行分配:

<local:MarginDataContext x:Key="MyDC" WindowInstance="{x:Reference MyWindow}"/>

实际上...这对我来说并不完全适用。在我的情况下,我不能使用x:Reference扩展:(有没有其他方法可以不使用x:Reference来完成它? - Goose
我正在使用的平台不支持x:Reference扩展。你的解决方案在标准WPF上运行得非常好,但是在我的特殊情况下,我不幸不能使用该扩展。 - Goose
我发现 x:Reference 是 XAML 2009 的一部分,尽管 XAML 2006 的命名空间也可以接受它。 - BlueM

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