2014-01-15 32 views
1

這裏是我的應用程序的佈局草圖:結合的ElementName位於遠在的VisualTree從菜單項

<UserControl> 
    <Grid> 
     <Grid.ColumnDefinitions>...</Grid.ColumnDefinitions> 
     <Grid.RowDefinitions>...</Grid.RowDefinitions> 
     <Border>...</Border> 
     <Grid>...</Grid> 
     <DataGrid Grid.Column="1" Grid.ColumnSpan="2" Grid.Row="2" AutoGenerateColumns="False" 
        HorizontalAlignment="Stretch" Name="myDataGrid" VerticalAlignment="Stretch" 
        ItemsSource="{Binding Path=MyModel.Files}" 
        SelectedItem="{Binding SelectedFile}"      
        Margin="0,0,10,3" CanUserReorderColumns="False" CanUserResizeRows="False" Style="{StaticResource DataGridStyle_Generic}" 
        IsReadOnly="True">...</DataGrid.ContextMenu> 
     </DataGrid> 
     <Border>...</Border> 
     <Border BorderBrush="Gray" BorderThickness="1" Grid.Row="4" Grid.Column="1" Grid.ColumnSpan="2" Margin="0,0,10,0"> 
      <Grid Margin="0,0,10,0"> 
       <Grid.ColumnDefinitions>...</Grid.ColumnDefinitions> 
       <Grid.RowDefinitions>...</Grid.RowDefinitions> 
       <StackPanel Grid.Row="1" Orientation="Horizontal" Margin="0,0,10,2"> 
        <Button>...</Button> 
        <Button Margin="0" Name="m_DropDownButton" Padding="0, 4" 
          HorizontalAlignment="Center" VerticalAlignment="Center"        
          ContextMenuService.IsEnabled="False" Click="m_DropDownButton_Click"> 
         <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center"> 
          <Path x:Name="BtnArrow" Margin="4" VerticalAlignment="Center" Width="6" Fill="#FF000000" Stretch="Uniform" HorizontalAlignment="Right" Data="F1 M 301.14,-189.041L 311.57,-189.041L 306.355,-182.942L 301.14,-189.041 Z "/> 
         </StackPanel> 
         <Button.ContextMenu> 
          <ContextMenu> 
           <MenuItem Header="All files" Command="{Binding AllFilesCommand}" /> 
           <MenuItem Header="Selected files only" 
              Command="{Binding SelectedFilesOnlyCommand}" 
              CommandParameter="{Binding Path=SelectedItems, ElementName=myDataGrid}"/>   
          </ContextMenu> 
         </Button.ContextMenu> 
        </Button> 
       </StackPanel> 
       <StackPanel Grid.Row="0" Orientation="Horizontal" VerticalAlignment="Stretch" Margin="0,0,10,0">...</StackPanel> 
      </Grid> 
     </Border> 
    </Grid> 
</UserControl> 

我想的myDataGridSelectedItems財產通過爲myMenuItem的司令部CommandParameter。我怎樣才能做到這一點?

注意#1:這兩個控件遠在Visual Tree中,它們的第一個共同父項是myGrid。無法找到任何工作解決方案,因爲我總是在輸出窗口中出現「無法找到綁定源」錯誤消息。

注意#2:DataGrid的SelectedItems屬性是隻讀的,因此不允許將其綁定到ViewModel屬性。

注意#3:我想避免代碼背後的任何代碼,例如爲DataGrid的SelectionChanged事件創建事件處理程序。

+0

上面的草圖是一個XAML文檔,還是隻是一個可視化樹轉儲? –

+0

你爲什麼要那樣做?一個'ContextMenu'是一個上下文菜單......它的上下文應該改變並且與你右鍵單擊的地方相關。那麼,爲什麼你會爲'Button'上的'DataGrid'項目提供右鍵點擊選項,這是在不同的'Panel'中?只需將'ContextMenu'放在它所屬的'DataGrid'上,所有問題都會消失。 – Sheridan

+0

@Sheridan該上下文菜單是一個按鈕的「下拉」菜單。該按鈕會執行網格中存在的數據的一些業務邏輯。但是,在上下文菜單中,用戶可以在「所有項目」和「所選項目」之間進行選擇。爲什麼是上下文菜單?這是一個相當便宜的解決方案,具有與WPF Toolkit的DropDownButton類似的控件。相反,我對解決方案感興趣。 – papaiatis

回答

1

我沒有嘗試謝里登的方式,這是值得一讀的恕我直言。

無論如何,你也可以嘗試下面的黑客:

   <Button Margin="0" Name="m_DropDownButton" Padding="0, 4" 
         HorizontalAlignment="Center" VerticalAlignment="Center"        
         ContextMenuService.IsEnabled="False" Click="m_DropDownButton_Click" 
         Tag="{Binding ElementName=myDataGrid}" 
         > 
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center"> 
         <Path x:Name="BtnArrow" Margin="4" VerticalAlignment="Center" Width="6" Fill="#FF000000" Stretch="Uniform" HorizontalAlignment="Right" Data="F1 M 301.14,-189.041L 311.57,-189.041L 306.355,-182.942L 301.14,-189.041 Z "/> 
        </StackPanel> 
        <Button.ContextMenu> 
         <ContextMenu> 
          <MenuItem Header="All files" Command="{Binding AllFilesCommand}" /> 
          <MenuItem Header="Selected files only" 
             Command="{Binding SelectedFilesOnlyCommand}" 
             CommandParameter="{Binding Path=PlacementTarget.Tag.SelectedItems, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}}"/> 
         </ContextMenu> 
        </Button.ContextMenu> 
       </Button> 

注按鈕和CommandParameter結合「變量」屬性。

還有一個小代碼隱藏,但我相信你有它還有:

private void m_DropDownButton_Click(object sender, RoutedEventArgs e) 
    { 
     var button = (Button)sender; 
     button.ContextMenu.PlacementTarget = button; 
     button.ContextMenu.IsOpen = true; 
    } 

讓我知道。

+0

這工作就像一個魅力! – papaiatis

1

您有一個棘手的要求履行,但有的解決方案。這有點漫長,也許有點痛苦,因爲你會有相當多的工作要做,但在這裏。

由於ContextMenu不是普通視覺樹的一部分,因此無法訪問此處定義的元素或DataContext的成員。要解決這個問題,你需要做兩件事(或者三件事)。首先要將屬性添加到視圖模型中,以便將數據綁定到DataGrid.SelectedItems屬性。

您必須做的第二件事是創建一個方法,在DataGrid.SelectedItems屬性上擁有TwoWay Binding,因爲'內置'屬性是隻讀的。幸運的是,這個主題在網上有很多帖子,涉及使用自定義綁定SelectedItems附加屬性。我假設你可以自己找到它們。

因此,現在假設您有權訪問視圖模型中的選定項或後面的代碼,接下來需要將ContextMenu.DataContext屬性設置爲您的視圖模型的實例。我們可以做的是使用ContextMenu.PlacementTarget財產和不斷有用Tag財產...試試這個:

<Button Tag="{Binding DataContext, RelativeSource={RelativeSource AncestorType={x:Type 
    Views:YourView}}}"> 
    <Button.ContextMenu> 
     <ContextMenu DataContext="{Binding PlacementTarget.Tag, RelativeSource={ 
      RelativeSource Self}}"> 
      <MenuItem /> 
      <MenuItem Name="myMenuItem" Command="{Binding DoAction}" 
       CommandParameter="{Binding SelectedItems}" /> 
     </ContextMenu> 
    </Button.ContextMenu> 
</Button> 

BindingTag屬性看起來綁定到父視圖的DataContext屬性的內容(WindowUserControl),假設它被命名爲YourView,並且您已爲您的視圖項目或名爲Views的文件夾設置了XML命名空間前綴。

接下來,ContextMenu.DataContextTag屬性設置爲相同的值,所以現在你ContextMenu同時訪問的SelectedItems財產的從視圖模型的命令。