2016-03-14 86 views
1

我試圖讓我的腳在地面上用WPF和MVVM了將近一年,但現在每次我想我明白它是如何工作的,或至少它是如何應該工作,出現了一些不起作用的東西,我無法理解或找出原因。也許你可以幫助我這個。WPF數據在文本菜單綁定:直接與資源

爲了簡單起見,我有一個非常基本的視圖模型:

Public Class MainViewModel 
    Private _testCommand As ICommand = New RelayCommand(AddressOf Me.Test) 
    Private _items As IEnumerable(Of String) = New String() {"Item 1", "Item 2", "Item 3"} 

    Public ReadOnly Property TestCommand As ICommand 
     Get 
      Return _testCommand 
     End Get 
    End Property 

    Private Sub Test() 
     MsgBox("Test") 
    End Sub 

    Public ReadOnly Property Items As IEnumerable(Of String) 
     Get 
      Return _items 
     End Get 
    End Property 

End Class 

我的DataContext的使用我有兩個ListView同樣帶有基本窗口這個視圖模型。

<Window x:Class="MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:local="clr-namespace:ContextMenuTest" 
     Title="MainWindow" Height="350" Width="525"> 

    <Window.DataContext> 
     <local:MainViewModel /> 
    </Window.DataContext> 

    <Window.Resources> 
     <ContextMenu x:Key="ItemContextMenu"> 
      <MenuItem Header="Test Left" Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListView}}, Path=DataContext.TestCommand}" /> 
     </ContextMenu> 

     <Style x:Key="TestItemStyle_Left" TargetType="{x:Type ListViewItem}"> 
      <Setter Property="ContextMenu" Value="{StaticResource ItemContextMenu}" /> 
     </Style> 

     <Style x:Key="TestItemStyle_Right" TargetType="{x:Type ListViewItem}"> 
      <Setter Property="ContextMenu"> 
       <Setter.Value> 
        <ContextMenu> 
         <MenuItem Header="Test Right" Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListView}}, Path=DataContext.TestCommand}" /> 
        </ContextMenu> 
       </Setter.Value> 
      </Setter> 
     </Style> 
    </Window.Resources> 

    <Grid> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="*" /> 
      <ColumnDefinition Width="*" /> 
     </Grid.ColumnDefinitions> 

     <ListView Grid.Column="0" ItemsSource="{Binding Items}" ItemContainerStyle="{StaticResource TestItemStyle_Left}"> 
      <ListView.View> 
       <GridView> 
        <GridViewColumn Header="Test" Width="100" DisplayMemberBinding="{Binding}" /> 
       </GridView> 
      </ListView.View> 
     </ListView> 

     <ListView Grid.Column="1" ItemsSource="{Binding Items}" ItemContainerStyle="{StaticResource TestItemStyle_Right}"> 
      <ListView.View> 
       <GridView> 
        <GridViewColumn Header="Test" Width="100" DisplayMemberBinding="{Binding}" /> 
       </GridView> 
      </ListView.View> 
     </ListView> 
    </Grid> 
</Window> 

兩個ListView可相同,他們只在他們所使用的ItemContainerStyle不同。 而且兩者ItemContainerStyle唯一在ContextMenu在工作的方式不同。在左側它的實現和使用作爲一種資源,右側則直接執行。

但爲什麼該命令的上下文菜單項的結合僅在左側,而不是右側工作?

謝謝您的解釋:-)

+0

[*如何綁定到數據不繼承DataContext的時候*](http://www.thomaslevesque.com/2011/03/21/WPF的如何做綁定到數據時,最DataContext的 - 是 - 不繼承/) – slugster

+0

但爲什麼在DataContext不是當它的工作左側繼承右側? – Nostromo

+0

咦?那個評論對我沒有意義? DataContext不被繼承,因爲上下文菜單不是可視或邏輯樹的一部分。這意味着你也無法搜索祖先。這從MSDN DOCO可能幫助:https://msdn.microsoft.com/en-us/library/system.windows.frameworkelement.datacontext(v=vs.110).aspx – slugster

回答

-1

如果你看一下在輸出窗口綁定錯誤,你會發現這一點。

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.ListView', AncestorLevel='1''. BindingExpression:Path=DataContext.TestCommand; DataItem=null; target element is 'MenuItem' (Name=''); target property is 'Command' (type 'ICommand')

您可以找到here解釋

+0

-1表示使用標籤屬性 - 這是不需要的,它是一種黑客技術,需要與舊的Visual Basic一起死掉。 – slugster

+0

@slugster,我不是建議使用Tag屬性,而是他想要的解釋以及綁定錯誤的解釋。 – Davy

+0

是的,我想你是對的在這方面的......但是你所做的一切都是鏈接到答案,而無需任何附加信息(包括作爲樣本並不能說明什麼* *和*爲什麼*和具有約束力的錯誤*如何固定*)。我可以建議你稍微補充一下你的答案 - 目前它只不過是一個鏈接到別人的答案。 – slugster