[英]RelativeSource binding on GridViewColumnHeader not working
[英]Binding returns RelativeSource object instead the one pointed by the binding
我必須將DataGrid
中列的Visibility
屬性綁定到主用戶控件的屬性。 DataGrid
位於用單獨的ResourceDictionary
編寫的DataTemplate
中。 我已經使用了這篇文章中描述的 ProxyFramework 元素技巧。 問題是代理元素內的綁定返回 System.Windows.Data.RelativeSource 類型的System.Windows.Data.RelativeSource
,而不是我需要的值。
這里的代碼示例:
主窗口.xaml
<Window
x:Class="TestRelativeSource.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:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"
xmlns:local="clr-namespace:TestRelativeSource"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
x:Name="WinRoot"
Title="MainWindow"
Width="800"
Height="450"
mc:Ignorable="d">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<local:DerivedResource />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TabControl
Name="MainTabControl"
ContentTemplate="{StaticResource MyDataTemplate}"
ItemsSource="{Binding Path=MyList, ElementName=WinRoot, diag:PresentationTraceSources.TraceLevel=High}">
</TabControl>
<Button
x:Name="button"
Grid.Column="1"
Width="72"
Margin="0,10,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Click="Button_Click"
Content="Test" />
<Button
x:Name="buttonVisible"
Grid.Column="1"
Width="72"
Margin="0,35,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Click="ButtonVisible_Click"
Content="TestVisible" />
</Grid>
</Window>
背后的代碼
namespace TestRelativeSource
{
public partial class MainWindow : Window, INotifyPropertyChanged
{
public MainWindow()
{
InitializeComponent();
}
private ObservableCollection<MyCollections> myList;
public ObservableCollection<MyCollections> MyList
{
get { return myList; }
set { myList = value; OnPropertyChanged(); }
}
private bool visible;
public bool MyVisible
{
get { return visible; }
set { visible = value; OnPropertyChanged(); }
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName]string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private void Button_Click(object sender, RoutedEventArgs e)
{
MyList = new ObservableCollection<MyCollections>();
var coll = new MyCollections();
coll.Name = "Test";
coll.Items = new ObservableCollection<MyItem>();
coll.Items.Add(new MyItem() { Name = "name1", TrueFalse = true });
coll.Items.Add(new MyItem() { Name = "name2", TrueFalse = false });
coll.Items.Add(new MyItem() { Name = "name3", TrueFalse = true });
coll.Items.Add(new MyItem() { Name = "name4", TrueFalse = false });
MyList.Add(coll);
}
private void ButtonVisible_Click(object sender, RoutedEventArgs e)
{
MyVisible= !MyVisible;
}
}
public class MyCollections : INotifyPropertyChanged
{
private string name;
public string Name
{
get { return name; }
set { name = value; OnPropertyChanged(); }
}
private ObservableCollection<MyItem> myVar;
public ObservableCollection<MyItem> Items
{
get { return myVar; }
set { myVar = value; OnPropertyChanged(); }
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName]string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public override string ToString()
{
return Name;
}
}
public class MyItem : INotifyPropertyChanged
{
private string _name;
private bool _trueFalse;
public string Name { get => _name; set { _name = value; OnPropertyChanged(); } }
public bool TrueFalse { get => _trueFalse; set { _trueFalse = value; OnPropertyChanged(); } }
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName]string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
派生資源.xaml
<ResourceDictionary
x:Class="TestRelativeSource.DerivedResource"
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:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"
xmlns:local="clr-namespace:TestRelativeSource"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<BooleanToVisibilityConverter x:Key="BoolToVis" />
<DataTemplate x:Key="MyDataTemplate">
<DockPanel>
<DataGrid
x:Name="MyDataGrid"
AutoGenerateColumns="False"
CanUserDeleteRows="False"
ItemsSource="{Binding Items, Mode=OneWay}">
<DataGrid.Resources>
************** this binding returns a System.Windows.Data.RelativeSource instead Window***************
<FrameworkElement x:Key="ElementTabTypeProxyElement" DataContext="{Binding Source={RelativeSource AncestorType={x:Type Window}}}" />
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn
Binding="{Binding Name, Mode=OneWay, FallbackValue='---'}"
Header="Name"
/>
<DataGridCheckBoxColumn
Binding="{Binding TrueFalse, Mode=OneWay, FallbackValue=false}"
Header="TrueFalse"
************Here I want a boolean to convert to visibility from the property MyVisible***************
Visibility="{Binding Source={StaticResource ElementTabTypeProxyElement}, Path=DataContext.MyVisible, Converter={StaticResource BoolToVis}, diag:PresentationTraceSources.TraceLevel=High}" />
</DataGrid.Columns>
</DataGrid>
</DockPanel>
</DataTemplate>
</ResourceDictionary>
我該如何解決這個問題? 謝謝
正如 ASh 所指出的,“{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}}”是正確的解決方案,但也在 xaml 中稍作修改:
<DockPanel>
<DockPanel.Resources>
<FrameworkElement x:Key="ElementTabTypeProxyElement" DataContext="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=MyVisible, diag:PresentationTraceSources.TraceLevel=High}" />
</DockPanel.Resources>
<ContentControl Content="{StaticResource ElementTabTypeProxyElement}" Visibility="Collapsed" />
<DataGrid
x:Name="MyDataGrid"
AutoGenerateColumns="False"
CanUserDeleteRows="False"
ItemsSource="{Binding Items, Mode=OneWay}">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Name, Mode=OneWay, FallbackValue='---'}" Header="Name" />
<DataGridCheckBoxColumn
Binding="{Binding TrueFalse, Mode=OneWay, FallbackValue=false}"
Header="TrueFalse"
Visibility="{Binding Source={StaticResource ElementTabTypeProxyElement}, Path=DataContext, Converter={StaticResource BoolToVis}, diag:PresentationTraceSources.TraceLevel=High}" />
</DataGrid.Columns>
</DataGrid>
</DockPanel>
因為我忘記了在可視樹中插入 ProxyElement 的虛擬 ContentControl
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.