Datagridcolumn:通过 BindingProxy 绑定可见性和宽度显示不同的行为

Datagridcolumn: Binding Visibility and Width via BindingProxy show different behavior

由于数据网格的列不在数据网格的可视化树中,我正在使用这种绑定代理的方法来绑定 DataGridTextColumn.

的可见性

https://www.thomaslevesque.com/2011/03/21/wpf-how-to-bind-to-data-when-the-datacontext-is-not-inherited/

出于某种原因,我想了解相同的方法确实适用于 Visibility 但不适用于专栏的 Width属性。 有人可以向我解释这种不同的行为吗?

代码示例

c#

class BindingProxy : Freezable
{
    #region Override of Freezable
    protected override Freezable CreateInstanceCore()
    {
        return new BindingProxy();
    }
    #endregion //Override of Freezable

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

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


public class Column : INotifyPropertyChanged
{

    public event PropertyChangedEventHandler PropertyChanged;
    protected internal void OnPropertyChanged(string propertyname)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyname));
    }

    public Column(bool visible = true)
    {
        if (visible == true)
            Visible = Visibility.Visible;
        else
            Visible = Visibility.Collapsed;

        Width = 200;
    }

    public Visibility Visible
    {
        get { return m_visible; }
        set { m_visible = value; OnPropertyChanged("Visible"); }
    }
    Visibility m_visible;

    public double Width
    {
        get { return m_width; }
        set { m_width = value; OnPropertyChanged("Width"); }
    }

    double m_width;
}

只是为了更容易重现

public partial class MainWindow : Window
{
    public MainWindow()
    {


        Lines = new ObservableCollection<tableline>();


        for (int i = 0; i< 5; i++)
            Lines.Add(new tableline());

        Columns = new List<Column>();
        Columns.Add(new Column(true));
        Columns.Add(new Column(false));

        InitializeComponent();
        DataContext = this;
    }

    public List<Column> Columns { get; set; }
    public ObservableCollection<tableline>Lines { get; set; }
}

public class tableline
{
    public tableline()
    {
        Result = new List<string>();
        int colCount = 2;
        for (int i = 0; i < colCount; i++)
        {
            Result.Add(i.ToString() + " some text");
        }

    }
    public List<string> Result { get; set; }
}

xaml

<DataGrid ItemsSource="{Binding Lines}" AutoGenerateColumns="False" >
    <DataGrid.Resources>
        <local:BindingProxy x:Key="proxy" Data="{Binding}"/>
    </DataGrid.Resources>
    <DataGrid.Columns>
        <DataGridTextColumn Header="ProductId1" Binding="{Binding Path=Result[0]}" Visibility="{Binding Data.Columns[0].Visible, Source={StaticResource proxy}}" Width="{Binding Data.Columns[0].Width, Source={StaticResource proxy}}" />
        <DataGridTextColumn Header="ProductId2" Binding="{Binding Path=Result[1]}" Visibility="{Binding Data.Columns[1].Visible, Source={StaticResource proxy}}" Width="{Binding Data.Columns[1].Width, Source={StaticResource proxy}}"/>
    </DataGrid.Columns>
</DataGrid>

只是想让你知道我最初的目标是什么。我想将所有列的宽度设置为自动,但在绘制数据网格期间使用 "maximum" 列宽。但是,用户应该可以调整大小超过此限制。这就是为什么我不能使用 MaxColumnWidth 所以我认为实现这一点的最简单方法是读取每一列的宽度并将其设置为 "maximum" 值(如果它大于限制)。

DataGridColumnWidth 属性 的类型是 DataGridLength 而不是 double

更改源类型属性:

public DataGridLength Width
{
    get { return m_width; }
    set { m_width = value; OnPropertyChanged("Width"); }
}

DataGridLength m_width;

BindingMode

<DataGridTextColumn Header="ProductId1" Binding="{Binding Path=Result[1]}"
                    Visibility="{Binding Data.Columns[0].Visible, Source={StaticResource proxy}}" 
                    Width="{Binding Data.Columns[0].Width, Source={StaticResource proxy}, Mode=TwoWay}" />