2015-05-14 67 views
1

我想綁定一個datagrid列寬度但不工作。如何綁定WPF中的datagrid列寬度(MVVM)

<DataGridTextColumn Binding="{Binding Name}" Width="{Binding GridNameWidth}" Header="Name" /> 

這裏是後端代碼:

public int GridNameWidth 
{ 
    get 
    { 
     return 300; 
    } 
} 

後端代碼是從來不碰。沒有錯誤,但name字段具有默認寬度。我想寬度綁定到我的財產。我不需要雙向綁定,只需要在網格加載時綁定寬度。這是可能的wpf?

+0

你的數據結構是什麼樣的?包含'Name'屬性的相同對象是否也包含您的'GridNameWidth'屬性? – Rachel

+0

正確,同一個對象包含我的Name對象。 – Luke101

+0

通過模型屬性設置視覺效果的寬度不是mvvm。 – Will

回答

6

DataGridTextColumn是一個抽象對象,它實際上並不是VisualTree的一部分,因此它不像使用其他控件那樣使用繼承的DataContext。

WPF知道如何正確解析類似Binding屬性的東西,並將綁定轉移到每個單元格,但像寬度這樣的東西只是按照原樣進行評估,並且沒有正確評估,因爲DataContext和VisualTree都沒有按預期方式出現。

一個常見的解決方案是使用靜態數據源代替您的綁定。下面是基於this answer一個例子,它採用x:Reference參考另一個控制從XAML標記:

{Binding Source={x:Reference MyDataGrid}, Path=DataContext.NameColumnWidth} 

或者,你可以與有它的寬度綁定到任何物業是在控制定義自己DataGridCellTemplate你DataItem

+0

這可能是正確的,但我仍然不明白。你是說我不應該使用我的'GridNameWidth'屬性,而是在窗口上使用另一個控件?我讀了另一個答案,但他沒有給出一個明確的例子。 – Luke101

+0

@ Luke101問題是當UI生成時DataGridTextColumn實際上不存在,所以綁定不能正確計算。作爲替代,我們可以將綁定設置爲在生成單元格時存在的靜態內容。 'Source = {x:Reference ...}'意思是「在XAML中找到名爲XXX的對象並將其用作此綁定的源」,因此理論上我們可以將其與'Path = DataContext.NameColumnWidth'結合使用告訴它使用來自'MyDataGrid.DataContext.NameColumnWidth'的值 – Rachel

-1

如果您希望它工作,則您的GridNameWidth應該是DataGridLength類型。

+1

有一個爲double類型定義的隱式轉換器。請參閱http://referencesource.microsoft.com/#PresentationFramework/Framework/System/Windows/Controls/DataGridLength.cs,334 – user2697817

+0

有沒有辦法讓它使用MVVM工作?如果不是,我會如何使用你的方式? – Luke101

+0

你可以使用雙。或者爲int實現一個值轉換器。 – user2697817

0

如前所述,這裏的問題是DataGridTextColumn不在邏輯或可視化樹中。 另一種解決方案是基於提供綁定的綁定代理的此方法。 https://stackoverflow.com/a/46787502/5381620

源碼

<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]}" Width="{Binding Data.Columns[0].Width, Source={StaticResource proxy}, Mode=TwoWay}" /> 
     <DataGridTextColumn Header="ProductId2" Binding="{Binding Path=Result[1]}" Width="{Binding Data.Columns[1].Width, Source={StaticResource proxy}, Mode=TwoWay}"/> 
    </DataGrid.Columns> 
</DataGrid> 

class BindingProxy : Freezable 
{ 
    //Override of Freezable 
    protected override Freezable CreateInstanceCore() 
    { 
     return new BindingProxy(); 
    } 
    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 DataGridLength Width 
    { 
     get { return m_width; } 
     set { m_width = value; OnPropertyChanged("Width"); } 
    } 
    DataGridLength m_width; 
} 

對於此實現直接使用List<Column>或在的ObservableCollection其他的DataContext調整結合。

+0

您可以添加一些關於如何實現該解決方案的更多描述? –

+0

我希望這有助於M. K. :-) – pedrito