簡體   English   中英

綁定返回 RelativeSource object 而不是綁定指向的那個

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM