1

何らかの条件で DataGrid の列を非表示にする必要がある場合、私たちは皆問題に直面しました。この問題を解決するには、少なくとも 2 つの方法があります。どちらのアプローチにもプロキシ要素が必要です。私はこれらのアプローチの両方を使用します。ご覧のとおり、FreezableProxyプロキシ要素としての使用には は必要ありませんContentControlが、追加のクラス ( FreezableProxy) を指定する必要があります。FrameworkElementをプロキシとして使用する場合、追加のクラス ( などFreezableProxy) を指定する必要はありませんがContentControl、マークアップに追加する必要があります。

XAML:

<Window.Resources>
    <SampleRadioBoxCheckedConverter:FreezableProxy x:Key="FreezableProxy" Data="{Binding}"/>
    <FrameworkElement x:Key="FrameworkElement" DataContext="{Binding}"/>
</Window.Resources>

<Grid Margin="10">
    <Grid.RowDefinitions>
        <RowDefinition></RowDefinition>
        <RowDefinition></RowDefinition>
    </Grid.RowDefinitions>
    <DataGrid AutoGenerateColumns="False">
        <DataGrid.Columns>
            <DataGridTextColumn Header="Name"/>
            <DataGridTextColumn Header="Type" 
                                Visibility="{Binding Data.IsPartnerColumnVisible, Source={StaticResource FreezableProxy}}"/>
            <DataGridTextColumn Header="Number" 
                                Visibility="{Binding DataContext.IsPartnerColumnVisible, Source={StaticResource FrameworkElement}}"/>

        </DataGrid.Columns>
    </DataGrid>
    <ContentControl Grid.Row="1" Content="{StaticResource FrameworkElement}" Visibility="Collapsed"></ContentControl>

</Grid>

分離コード:

public class FreezableProxy : Freezable
{
    protected override Freezable CreateInstanceCore()
    {
        return new FreezableProxy();
    }

    public object Data
    {
        get { return (object)GetValue(DataProperty); }
        set { SetValue(DataProperty, value); }
    }

    public static readonly DependencyProperty DataProperty =
        DependencyProperty.Register("Data", typeof(object),
                                        typeof(FreezableProxy));
}

public partial class MainWindow : INotifyPropertyChanged
{
    private Visibility _isPartnerColumnVisible = Visibility.Hidden;
    public Visibility IsPartnerColumnVisible
    {
        get
        {
            return _isPartnerColumnVisible;
        }
        set
        {
            _isPartnerColumnVisible = value;
            RaisePropertyChanged("IsPartnerColumnVisible");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    void RaisePropertyChanged(String prop)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(prop));
    }

    public MainWindow()
    {
        InitializeComponent();
        DataContext = this;
    }
}

どちらのアプローチも非常に似ています。2 番目のアプローチ (を使用FrameworkElement) を使用することをお勧めします。次に、質問があります-実際に設定されてContentControlいる場合、追加を指定する必要があるのはなぜですか? 魔法は何をしているの?使用する場合、何かを指定する必要はなく、正常に機能します。Binding{StaticResource FrameworkElement}ContentControlFrezableProxyContentControl-s

アップデート

<FrameworkElement x:Key="FrameworkElement" DataContext="{Binding}"/>
/////<ContentControl Grid.Row="1" Content="{StaticResource FrameworkElement}" Visibility="Collapsed"></ContentControl>

なぜこれが機能しないのですか?ContentControl はコメントされていDataContextますが、プロパティをFrameworkElement明示的に設定しています。

4

2 に答える 2

3

問題は、DataGridColumns がその親 dataGrid と同じビジュアル ツリーにないことです。したがって、DataContext が継承されていないためバインドが機能しません。Visual Tree に依存しているため、RelativeSource を使用して見つけることができません。

したがって、言及されているすべてのアプローチは、DataContext を列に渡すことです。


ここで、2 つのアプローチの違いについて説明します。

FreezableProxy アプローチ:

このための実際のソース リファレンスはhereです。Freezable の背後にある魔法はここで定義されているため、同じリンクから引用します。

Freezable クラスの主な目的は、変更可能で読み取り専用の状態を持つオブジェクトを定義することですが、この場合の興味深い機能は、Freezable オブジェクトがビジュアル ツリーまたは論理ツリーにない場合でも DataContext を継承できることです

したがって、Freezable を配置すると、継承された DataContext が自動的に取得されるため、ContentControl やプロキシ コントロールは必要ありません。


FrameworkElement + ContentControl アプローチ:

DataContext プロパティは flag で宣言されていますFrameworkMetadataOptions.Inherits。子コントロールに明示的に設定されていない限り、子コントロールは親要素から自動的に継承することを意味します。

したがって、ContentControl は Grid から自動的に DataContext を継承し、ContentControl の子要素は ContentControl から継承します。そのため、FrameworkElement は ContentControl から継承します。(DataContext を手動でバインドする必要はありません) . これはうまくいきます:

<FrameworkElement x:Key="FrameworkElement"/>

別のアプローチは、ここで私の回答でx:Reference説明されているように使用することです。

于 2014-08-26T12:15:19.740 に答える