2012-09-20 120 views
1

我在WPF MVVM應用程序中設置了Xceed數據網格,該應用程序設置爲保存主 - 細節記錄。當選擇一個子行時,我希望ViewModel檢測所選的子元素。我希望在零代碼隱藏的情況下執行此操作。我已經編寫了代碼,當單擊某個上下文菜單時,將對選定的項目執行操作。這可以在選擇父項時正常工作,但在選擇子項時總是返回null。Xceed Datagrid在子選擇時丟失SelectedItem

我已經把什麼我試圖acheive一個非常簡化的版本:

我的XAML是:

<Window x:Class="MasterDetailSelection.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:xcdg="clr-namespace:Xceed.Wpf.DataGrid;assembly=Xceed.Wpf.DataGrid.v4.2" 
    Title="MainWindow" Height="350" Width="525"> 
    <Grid> 
     <Grid.Resources> 
      <xcdg:DataGridCollectionViewSource x:Key="cvs_parents" Source="{Binding Path=Parents}"> 
       <xcdg:DataGridCollectionViewSource.DetailDescriptions> 
        <xcdg:PropertyDetailDescription RelationName="Children" 
                AutoCreateDetailDescriptions="False"> 
        </xcdg:PropertyDetailDescription> 
       </xcdg:DataGridCollectionViewSource.DetailDescriptions> 
      </xcdg:DataGridCollectionViewSource> 
     </Grid.Resources> 
     <xcdg:DataGridControl x:Name="ParentGrid" 
           NavigationBehavior="RowOnly" 
           ItemsSource="{Binding Source={StaticResource cvs_parents}}" 
           SelectedItem="{Binding SelectedItem}" 
      AutoCreateDetailConfigurations="True" 
           ReadOnly="True"> 
      <xcdg:DataGridControl.ContextMenu> 
       <ContextMenu DataContext="{Binding PlacementTarget, RelativeSource={RelativeSource Self}}"> 
        <MenuItem Header="Execute Command" 
           CommandParameter="{Binding DataContext.SelectedItem}" 
           Command="{Binding DataContext.SampleCommand}" /> 
       </ContextMenu> 
      </xcdg:DataGridControl.ContextMenu> 
     </xcdg:DataGridControl> 

    </Grid> 
</Window> 

視圖模型是:

namespace MasterDetailSelection 
{ 
    using System; 
    using System.Collections.Generic; 
    using System.Collections.ObjectModel; 
    using System.ComponentModel; 
    using Microsoft.Practices.Composite.Presentation.Commands; 

    public class ViewModel : INotifyPropertyChanged 
    { 
     private ObservableCollection<Parent> _parents; 
     public event PropertyChangedEventHandler PropertyChanged; 
     private DelegateCommand<Object> _sampleCommand; 
     private object _selectedItem; 

     public ObservableCollection<Parent> Parents 
     { 
      get { return _parents; } 

      set 
      { 
       _parents = value; 
       OnPropertyChanged("Parents"); 
      } 
     } 

     public DelegateCommand<Object> SampleCommand 
     { 
      get 
      { 
       if (_sampleCommand == null) 
       { 
        _sampleCommand = new DelegateCommand<object>(ExecuteSampleCommand, CanExecuteSampleCommand); 
        OnPropertyChanged("SampleCommand"); 
       } 
       return _sampleCommand; 
      } 
     } 

     public bool CanExecuteSampleCommand(Object commandParameter) 
     { 
      return true; 
     } 

     public void ExecuteSampleCommand(Object commandParameter) 
     { 
      Console.WriteLine("ExecuteSampleCommand"); 
     } 

     public object SelectedItem 
     { 
      get { return _selectedItem; } 
      set 
      { 
       if (_selectedItem != value) 
       { 
        _selectedItem = value; 
        OnPropertyChanged("SelectedItem"); 
       } 
      } 
     } 

     public void LoadParents() 
     { 
      var parents = new ObservableCollection<Parent>() 
       { 
        new Parent() 
         { 
          Id=1, 
          Description = "Parent1", 
          Children = new List<Child>(){new Child() {Id = 1, Description = "Child1"} } 
         } 
       }; 

      Parents = parents; 
     } 

     private void OnPropertyChanged(string propertyName) 
     { 
      if (PropertyChanged != null) 
      { 
       PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
      } 
     } 
    } 
} 

有2簡單實體:

public class Parent 
{ 
    public int Id { get; set;} 
    public string Description { get; set;} 
    public IEnumerable<Child> Children { get; set;} 
} 
public class Child 
{ 
    public int Id { get; set; } 
    public string Description { get; set; } 
} 

在App.xaml.cs的OnStartup覆蓋包含以下內容:

var viewModel = new ViewModel(); 
var window = new MainWindow(); 
window.DataContext = viewModel; 
viewModel.LoadParents(); 
window.Show(); 

每當我選擇父行中,二傳的SelectedItem被稱爲具有佔據的對象。當我選擇一個子行時,同一個setter被調用,但是有一個空值。

當在子行上單擊上下文菜單時,是否有任何方法可以獲取對所選項目的引用 - 並且在沒有代碼隱藏的情況下執行此操作。如果沒有,是否有可能使用代碼隱藏?

回答

0

也許你應該在下面的單元格或行上直接設置上下文菜單。然後您可以將相應的模型發送到該命令。在下面的例子中,我使用了一個靜態定位器類,它有我的虛擬機來綁定實際的命令。

<Style TargetType="{x:Type xcdg:DataCell}"> 
    <Setter Property="ContextMenu" Value="{StaticResource CellContextMenu}"> 
     <Setter.Value> 
      <ContextMenu> 
       <MenuItem Header="Execute Command" 
          CommandParameter="{Binding}" 
          Command="{Binding Source={StaticResource Locator} Path=ViewModel.SampleCommand}" /> 
      </ContextMenu> 
     </Setter.Value> 
    </Setter> 
</Style>