web-dev-qa-db-ja.com

WPFのDataGridColumnのバインドの可視性

バインディングを介してWPF DataGridの列を非表示にするにはどうすればよいですか?

これは私がやったことです:

<DataGridTextColumn Header="Column header"
                    Binding="{Binding ColumnValue}"
                    Width="100"
                    ElementStyle="{StaticResource DataGridRightAlign}"
                    Visibility="{Binding MyColumnVisibility}" />

そして、これは私が得たものです(列がまだ表示されていることに加えて):

System.Windows.Dataエラー:2:ターゲット要素の管理FrameworkFrameworkまたはFrameworkContentElementが見つかりません。 BindingExpression:Path = MyColumnVisibility; DataItem = null;ターゲット要素は 'DataGridTextColumn'(HashCode = 1460142);ターゲットプロパティは 'Visibility'(タイプ 'Visibility')です

統治の意味がわからない。私の窓のどこかに、何が機能し何が機能しないかを決定する大統領がいますか?または、何かに投票する必要がありますか?

Webで解決策を検索しているときに、タイトルは有望だ​​が、まったく無関係または再現不可能なコンテンツを含む12ページほどが見つかりました。したがって、これが問題に関する最初の質問のようです。何か案が?

59
ygoe

まず、DataGridTextColumnまたはサポートされている他のdataGrid列は、DataGridのビジュアルツリーにありません。したがって、デフォルトではDataContextDataGridを継承しません。ただし、Binding DPでのみ機能し、DataGridColumn上の他のDPでは機能しません。

なぜなら、それらは同じVisualTreeにないので、RelativeSourceを使用してDataContextを取得しようとしても、DataGridはDataGridまで移動できないため、同様に機能しません。

ただし、それを実現するには2つの方法があります。


最初Freezableクラスを使用-Freezableオブジェクトは、ビジュアルツリーまたは論理ツリーにない場合でもDataContextを継承できます。そのため、それを利用して利用することができます。

XAMLでバインドするために使用できるFreezableおよびData DPから継承するクラスを最初に作成します。

public class BindingProxy : Freezable
{
    #region Overrides of Freezable

    protected override Freezable CreateInstanceCore()
    {
        return new BindingProxy();
    }

    #endregion

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

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

次に、DataGridのインスタンスをDataGridリソースに追加して、DataGridのDataContextを継承し、そのデータDPにバインドできるようにします。

    <DataGrid>
        <DataGrid.Resources>
            <local:BindingProxy x:Key="proxy" Data="{Binding}"/>
        </DataGrid.Resources>
        <DataGrid.Columns>
            <DataGridTextColumn Visibility="{Binding Data.MyColumnVisibility,
                                                Source={StaticResource proxy}}"/>
        </DataGrid.Columns>
    </DataGrid>

SecondElementNameまたはx:Referenceを使用してXAMLの任意のUI要素を参照できます。ただし、ElementNameは同じビジュアルツリーでのみ機能しますが、x:Referenceにはこのような制約はありません。

そのため、それを有利に使用することもできます。 Visibilityをcollapsedに設定して、XAMLでダミーFrameworkElementを作成します。 FrameworkElementは、WindowまたはUserControlの親コンテナからDataContextを継承します。

DataGridでそれを使用できます。

    <FrameworkElement x:Name="dummyElement" Visibility="Collapsed"/>
    <DataGrid>
        <DataGrid.Columns>
            <DataGridTextColumn Header="Test"
                                Binding="{Binding Name}"
                                Visibility="{Binding DataContext.IsEnable,
                                          Source={x:Reference dummyElement}}"/>
        </DataGrid.Columns>
    </DataGrid>
141
Rohit Vats
<Window.Resources>
    <ResourceDictionary>
        <FrameworkElement x:Key="ProxyElement" DataContext="{Binding}" />
    </ResourceDictionary>
</Window.Resources>

<!-- Necessary for binding to resolve: adds reference to ProxyElement to tree.-->
<ContentControl Content="{StaticResource ProxyElement}" Visibility="Collapsed" />
<mch:MCHDataGrid Height="350"
                  AutoGenerateColumns="False"
                  FlowDirection="LeftToRight"
                  ItemsSource="{Binding PayStructures}"
                  SelectedItem="{Binding SelectedItem}">
    <DataGrid.Columns>
         <DataGridTemplateColumn Width="70"
                                 Header="name"
                                 IsReadOnly="True"
                                 Visibility="{Binding DataContext.IsShowName,
                                 Source={StaticResource ProxyElement}}">
             <DataGridTemplateColumn.CellTemplate>
                 <DataTemplate>
                     <TextBlock Text="{Binding FieldName}" />
                 </DataTemplate>
             </DataGridTemplateColumn.CellTemplate>
         </DataGridTemplateColumn>                   
     </DataGrid.Columns>
</mch:MCHDataGrid>

ビューモデルのバインドプロパティのサンプル:

private Visibility _isShowName;

public Visibility IsShowName
{
    get { return _isShowName; }
    set
    {
        _isShowName = value;
        OnPropertyChanged();
    }
}
12
Meysam Chegini