2015-11-13 110 views
2

我已將我的問題簡化爲一個最小的示例:我的DataGrid由ControlTemplate定義,並且在該ControlTemplate中,我無法綁定到ViewModel中的任何內容。從ControlTemplate綁定到ViewModel

這是簡化的視圖模型:

public class ViewModel : PropertyChangedBase 
{ 
    private string text1; 

    public ViewModel() 
    { 
     this.text1 = "tx1!"; 
    } 

    public string Text1 
    { 
     get { return text1; } 
     set 
     { 
      if (value == text1) return; 
      text1 = value; 
      NotifyOfPropertyChange(() => Text1); 
     } 
    } 
} 

我試圖結合Text1用幾種方法。大多數的事情,我通過谷歌找到建議FindAncestor但它沒有工作,要麼:

<Window x:Class="DataGridTemplateBinding.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:local="clr-namespace:DataGridTemplateBinding" 
     Title="MainWindow" Height="350" Width="525" 
     x:Name="LayoutRoot" 
     > 
    <Window.Resources> 
     <ControlTemplate x:Key="TableTemplate"> 
      <DataGrid> 
       <DataGrid.Columns> 
        <DataGridTextColumn Header="Column 1" /> 
        <!-- by ElementName --> 
        <DataGridTextColumn Header="{Binding DataContext.Text1, ElementName=LayoutRoot}" /> 
        <DataGridTextColumn Header="{Binding Text1, ElementName=LayoutRoot}" /> 

        <!-- by Ancestor type (Window) --> 
        <DataGridTextColumn Header="{Binding DataContext.Text1, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" /> 
        <DataGridTextColumn Header="{Binding Text1, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" /> 

        <!-- by templated parent --> 
        <DataGridTextColumn Header="{Binding DataContext.Text1, RelativeSource={RelativeSource TemplatedParent}}" /> 
        <DataGridTextColumn Header="{Binding Text1, RelativeSource={RelativeSource TemplatedParent}}" /> 

        <!-- by self?? --> 
        <DataGridTextColumn Header="{Binding DataContext.Text1, RelativeSource={RelativeSource Self}}" /> 
        <DataGridTextColumn Header="{Binding Text1, RelativeSource={RelativeSource Self}}" /> 

        <DataGridTextColumn Header="{Binding Content.DataContext.Text1, RelativeSource={RelativeSource TemplatedParent}}" /> 
        <DataGridTextColumn Header="{Binding Content.Text1, RelativeSource={RelativeSource TemplatedParent}}" /> 

        <DataGridTextColumn Header="{Binding DataContext.Text1}" /> 
        <DataGridTextColumn Header="{Binding Text1}" /> 

        <DataGridTextColumn Header="Column End" /> 
       </DataGrid.Columns> 
      </DataGrid> 
     </ControlTemplate> 
    </Window.Resources> 
    <Window.DataContext> 
     <local:ViewModel /> 
    </Window.DataContext> 
    <Grid> 
     <DataGrid Template="{StaticResource TableTemplate}" /> 
    </Grid> 
</Window> 

如何可以在模板中綁定到視圖模型的任何一列?我無法想象這是不可能的。


爲了完整,這些是記錄到輸出的錯誤。他們的訂單確實是而不是與XAML的順序一致。

System.Windows.Data Error: 40 : BindingExpression path error: 'DataContext' property not found on 'object' ''DataGridTextColumn' (HashCode=28365320)'. BindingExpression:Path=DataContext.Text1; DataItem='DataGridTextColumn' (HashCode=28365320); target element is 'DataGridTextColumn' (HashCode=28365320); target property is 'Header' (type 'Object')

System.Windows.Data Error: 40 : BindingExpression path error: 'Text1' property not found on 'object' ''DataGridTextColumn' (HashCode=54811268)'. BindingExpression:Path=Text1; DataItem='DataGridTextColumn' (HashCode=54811268); target element is 'DataGridTextColumn' (HashCode=54811268); target property is 'Header' (type 'Object')

System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=DataContext.Text1; DataItem=null; target element is 'DataGridTextColumn' (HashCode=55195297); target property is 'Header' (type 'Object')

System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=Text1; DataItem=null; target element is 'DataGridTextColumn' (HashCode=38845522); target property is 'Header' (type 'Object')

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Window', AncestorLevel='1''. BindingExpression:Path=DataContext.Text1; DataItem=null; target element is 'DataGridTextColumn' (HashCode=2399386); target property is 'Header' (type 'Object')

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Window', AncestorLevel='1''. BindingExpression:Path=Text1; DataItem=null; target element is 'DataGridTextColumn' (HashCode=31265986); target property is 'Header' (type 'Object')

System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=DataContext.Text1; DataItem=null; target element is 'DataGridTextColumn' (HashCode=6837024); target property is 'Header' (type 'Object')

System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=Text1; DataItem=null; target element is 'DataGridTextColumn' (HashCode=17422861); target property is 'Header' (type 'Object')

System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=Content.DataContext.Text1; DataItem=null; target element is 'DataGridTextColumn' (HashCode=32669489); target property is 'Header' (type 'Object')

System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=Content.Text1; DataItem=null; target element is 'DataGridTextColumn' (HashCode=22361045); target property is 'Header' (type 'Object')

System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=DataContext.Text1; DataItem=null; target element is 'DataGridTextColumn' (HashCode=7953856); target property is 'Header' (type 'Object')

System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=Text1; DataItem=null; target element is 'DataGridTextColumn' (HashCode=65911433); target property is 'Header' (type 'Object')

+0

一個簡單的'{Binding Text1}'應該這樣做。你是否在其他地方設置'DataContext'? –

+0

所以你的'DataGrid'在它的模板中有另一個'DataGrid'? –

+0

@MikeEason不幸的是,一個簡單的「{Binding Text1}」並不能解決問題。 DataContext僅爲Window設置。 App.xaml&co。是標準的,這幾乎是最小示例項目中的所有代碼。 – ZoolWay

回答

2

設置HeaderTemplateDataGridTextColumn如下所示

<DataGridTextColumn > 
    <DataGridTextColumn.HeaderTemplate> 
     <DataTemplate> 
      <TextBlock Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.Text1}"></TextBlock> 
     </DataTemplate> 
    </DataGridTextColumn.HeaderTemplate> 
</DataGridTextColumn> 
+0

這很好,工作!不會因爲(請參閱我的回答)'DataGridTextColumn'不在樹中 - 使用'Header'的DataTemplate'工作,不知道爲什麼。不幸的是,我不能用它來綁定'可見性',但這不在我的問題中;) – ZoolWay

0

與所有我發現DataGridTextColumn是視覺樹也不邏輯樹的的無分的提示。這應該是爲什麼ElementNameRelativeSource不起作用的原因。關於DataGridTextColumn這個答案解釋,並給出了Sourcex:Reference一個可能的解決方案:DataGridTextColumn Visibility Binding

@Anand穆拉利的答覆工作,但不能應用於Visibility - 這是不是問題的一部分,因爲我minimalized那了。所以我接受這個,並會在這一個中提供更多的信息。

使用x:ReferenceVisibility它可以變成這樣的:

<DataGridTextColumn Binding="{Binding Data.OrderNumber}" Header="Order Number" Visibility="{Binding DataContext.ShowColumnOrderNumber, Source={x:Reference LayoutRoot}, Converter={StaticResource BooleanToVisibilityConverter}}" /> 

但是:我在我的例子中,我使用ControlTemplate並有x:Reference來解決這個模板必須是.Resources XAML部分範圍內的同一文件不能在外部ResourceDictionary。在後一種情況下,參考不起作用,因爲它無法解決。 (如果有人知道一個解決方案,它會受到歡迎)