WPF 绑定到资源中的元素

Posted

技术标签:

【中文标题】WPF 绑定到资源中的元素【英文标题】:WPF binding to elements in resources 【发布时间】:2018-07-18 16:12:48 【问题描述】:

我无法让 ListBox 元素始终可见。

我有ListBox,您可以在其中选择DataGrid。显示的名称绑定到 DataGrid Tag。选中的DataGrid 显示在下方。 DataGrid 名称,或者更确切地说,它的 Tag 绑定到来自 Content 类的数组。问题是 ListBox 元素在您选择它们​​之前是不可见的,当您选择它们​​时,只会显示所选项目的名称。

当我选择第二个元素时,第一个元素不再显示,反之亦然。

这是我的代码:

XAML:

<Window x:Class="WpfApp1.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:WpfApp1"
            xmlns:col="clr-namespace:System.Collections;assembly=mscorlib"
            mc:Ignorable="d"
            Title="MainWindow" Height="450" Width="525">
        <Window.Resources>
            <col:ArrayList x:Key="dataGridDef">
                <DataGrid Name="DG1" ItemsSource="Binding Path=List1" AutoGenerateColumns="False" 
                          Tag="Binding Path=GridNames[0]">
                    <DataGrid.Columns>
                        <DataGridTextColumn Header="Grid1Name1" Binding="Binding Path=Name1"/>
                    </DataGrid.Columns>
                </DataGrid>
                <DataGrid Name="DG2" ItemsSource="Binding Path=List2"  AutoGenerateColumns="False"
                          Tag="Binding Path=GridNames[1]">
                    <DataGrid.Columns>
                        <DataGridTextColumn Header="Grid2Name1" Binding="Binding Path=Name1"/>
                    </DataGrid.Columns>
                </DataGrid>
            </col:ArrayList>
        </Window.Resources>
        <StackPanel>
            <ListBox x:Name="lb" ItemsSource="StaticResource dataGridDef" DisplayMemberPath="Tag"
                     SelectedValue="Binding Path=SelectedGrid"/>
            <ContentControl Content="Binding ElementName=lb, Path=SelectedItem"/>
            <TextBlock Height="100" Text="Binding Path=Str.Header"/>
            <TextBlock Text="Binding Path=SelectedGrid.Tag"/>
        </StackPanel>
    </Window>

C#:

public partial class MainWindow : Window
    
        public MainWindow()
        
            InitializeComponent();
            DataContext = new Content();
        
    

    public class Content
    
        public ObservableCollection<Asd> List1  get; set; 
        public ObservableCollection<Asd> List2  get; set; 
        public DataGrid SelectedGrid  get; set; 

        private string[] _gridName;
        public string[] GridNames  get  return _gridName;  

        public Content()
        
            List1 = new ObservableCollection<Asd>();
            List2 = new ObservableCollection<Asd>();
            List1.Add(new Asd  Name1 = "1" );
            List1.Add(new Asd  Name1 = "2" );
            List2.Add(new Asd  Name1 = "a" );
            List2.Add(new Asd  Name1 = "b" );
            _gridName = new string[]  "G1", "G2" ;
        
    
    public class Asd: INotifyPropertyChanged
    
        private string _name1;
        public string Name1
        
            get  return _name1; 
            set
            
                if (value == _name1) return;
                _name1 = value;
                OnPropertyChanged(nameof(Name1));
            
        
        public event PropertyChangedEventHandler PropertyChanged;
        internal void OnPropertyChanged(string propertyName)
        
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        
    

【问题讨论】:

【参考方案1】:

您可以通过定义binding source for your resource 来解决此问题。

    为您的窗口命名。例如 x:Name=MyWindow。

    定义数据网格的绑定,使其源为 MyWindow:

    Tag="Binding Path=DataContext.GridNames[0], Source=x:Reference MyWindow"

结果:

这是完整的 XAML:

<Window x:Class="WpfApp6.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:WpfApp6"
    xmlns:collections="clr-namespace:System.Collections;assembly=mscorlib"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525" x:Name="MyWindow">
<Window.Resources>
    <collections:ArrayList x:Key="dataGridDef">
        <DataGrid Name="DG1" ItemsSource="Binding Path=List1" AutoGenerateColumns="False" Tag="Binding Path=DataContext.GridNames[0], Source=x:Reference MyWindow">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Grid1Name1" Binding="Binding Path=Name1"/>
            </DataGrid.Columns>
        </DataGrid>
        <DataGrid Name="DG2" ItemsSource="Binding Path=List2"  AutoGenerateColumns="False" Tag="Binding Path=DataContext.GridNames[1], Source=x:Reference MyWindow">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Grid2Name1" Binding="Binding Path=Name1"/>
            </DataGrid.Columns>
        </DataGrid>
    </collections:ArrayList>
</Window.Resources>
<StackPanel>
    <ListBox x:Name="lb" ItemsSource="StaticResource dataGridDef" DisplayMemberPath="Tag" SelectedValue="Binding Path=SelectedGrid, Mode=TwoWay"/>
    <ContentControl Content="Binding ElementName=lb, Path=SelectedItem"/>
    <TextBlock Height="100" Text="Binding Path=Str.Header"/>
    <TextBlock Text="Binding Path=SelectedGrid.Tag"/>
</StackPanel>

【讨论】:

以上是关于WPF 绑定到资源中的元素的主要内容,如果未能解决你的问题,请参考以下文章

WPF 与 Silverlight - 资源中的数据绑定

通过 WPF 中的绑定动态设置资源样式

WPF 非元素类绑定Binding之 Source 属性

2021-11-26 WPF面试题 WPF 中的资源是什么?

WPF实现主题更换的简单DEMO

WPF ComboBox 使用 ResourceBinding 动态绑定资源键并支持语言切换