首页 > 解决方案 > 如何从模板中访问主 DataContext

问题描述

概括

我在数据模板中有一个元素,我想将其绑定到主数据上下文的某些属性。我意识到在这种特定情况下,不同的解决方案可能更可取(我有一个可以避免这种情况的工作解决方案),但我怀疑这种问题可能会再次出现,我想知道在一般情况下如何解决它.

以下是我的具体情况。

细节

数据层次结构:我有一个类型列表A,每个实例A都有一个类型列表B,每个实例B都有一些其他数据,包括string文本日志。

UI 结构:我有一个ComboBox要选择的项目类型A。我有一个TabControl代表 type 项目的选项卡B,取自A上面的选择。在每个选项卡中,都有一种方法可以输入数据以填充类型的对象B和一个日志,表示对该实例的更改B

支持逻辑SelectionA:我在每个列表中使用属性(以及SelectionB在数据上下文中)跟踪所选项目,这些属性MainWindowViewModel会在它们更改时发出通知。该B对象还会在其日志文本更改时发出通知。这些确保 UI 响应对支持数据的更改。

问题:我想将通知逻辑全部移动到一个地方(即DataContext,即MainWindowViewModel),而不是在B类中有一些并且需要复制通知逻辑。为此,我添加了一个属性 ( SelectionBLogText) 来跟踪对象的LogText属性SelectionB,并将日志(在模板化选项卡面板中)绑定到主SelectionBLogText属性。问题是在标签页中,我似乎只能绑定到选定B对象的属性(从选定的选项卡),而我需要绑定到的属性DataContext。我尝试过使用RelativeSource,但到目前为止我没有尝试过任何工作,而且我看文档越多,我就越觉得它是为另一份工作而设计的。

XAML(删除了不相关的细节):

<Window x:Class="WPFQuestion.MainWindow"
        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:WPFQuestion"
        mc:Ignorable="d"

        Title="MainWindow"
        Height="350"
        Width="930">
    <DockPanel>
        <ComboBox
            ItemsSource="{Binding ListOfA}"
            SelectedItem="{Binding SelectionA}"
            DisplayMemberPath="Name"/>
        <TabControl
            ItemsSource="{Binding SelectionA}"
            SelectedItem="{Binding SelectionB}"
            DisplayMemberPath="Name">
            <TabControl.ContentTemplate>
                <ItemContainerTemplate>
                    <StackPanel>
                        <TextBox
                            IsReadOnly="True"
                            Text="{Binding Path=???.SelectionBLogText}"/>
                        <Button Click="ClearLogButton_Click"/>
                    </StackPanel>
                </ItemContainerTemplate>
            </TabControl.ContentTemplate>
        </TabControl>
    </DockPanel>
</Window>

和代码隐藏:

public partial class MainWindow : Window
{
    internal MainWindowViewModel vm;
    public MainWindow()
    {
        InitializeComponent();
        vm = new MainWindowViewModel();
        DataContext = vm;
    }
    // Various methods for event handling
}

public class A : IEnumerable<B>
{
    public string Name { get; set; }
    public List<B> Bs { get; set; }
}

public class B // previously : INotifyPropertyChanged
{
    public string Name { get; set; }
    public string LogText { get; set; }

    // various other properties
}

public class MainWindowViewModel : INotifyPropertyChanged
{
    private A _a;
    private B _b;

    public event PropertyChangedEventHandler PropertyChanged;

    public List<A> ListOfA { get; set; }

    public A SelectionA
    {
        get => _a;
        set
        {
            if (_a == value)
            {
                return;
            }
            _a = value;
            RaisePropertyChanged(nameof(SelectionA));
        }
    }

    public B SelectionB
    {
        get => _b;
        set
        {
            if (_b == value)
            {
                return;
            }
            _b = value;
            RaisePropertyChanged(nameof(SelectionB));
            RaisePropertyChanged(nameof(SelectionBLogText));
        }
    }

    public string SelectionBLogText
    {
        get => SelectionB.LogText;
        set
        {
            if (SelectionB.LogText == value)
            {
                return;
            }
            SelectionB.LogText = value;
            RaisePropertyChanged(nameof(SelectionBLogText));
        }
    }

    private void RaisePropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

标签: c#wpfdatatemplate

解决方案


当您使用相对绑定时,您是否尝试过这样的事情?如果没有,请检查一下。

     <TextBox IsReadOnly="True"
             Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window},
             Path=Datacontext.SelectionBLogText}"/>

推荐阅读