简体   繁体   中英

WPF MVVM - Get access to DependencyProperty of DataGrid in View from ViewModel

In my View I have a DataGrid which stores objects of 2 descending types. Every row has a Button with a Command connected to the ViewModel. In the ViewModel I need to find out which type of object has been chosen.

The question is what is the best and simple way of accessing SelectedItem property of the DataGrid from the Execute command method in a ViewModel?

So far I did it like this:

var window = Application.Current.Windows.OfType<Window>()
    .SingleOrDefault(x => x.IsActive);

var dataGrid = (DataGrid) window.FindName("MyGridName");
...

UPDATE - Xaml:

<DataGrid Name="MyGridName" ItemsSource="{Binding Elements}"
          AutoGenerateColumns="False" CanUserAddRows="False"
          CanUserDeleteRows="False" IsReadOnly="True">
  <DataGrid.Columns>
    <DataGridTemplateColumn Width="auto">
      <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
          <Button Name="OptionsBtn" Margin="5" Width="auto"
                  Height="30" Content="Options"
                  Command="{Binding ElementName=ElementsViewWindow,
                      Path=DataContext.ShowOptionsMenuCommand}"/>
        </DataTemplate>
      </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn>
  </DataGrid.Columns>
</DataGrid>

If you take the right MVVM approach this is very easy to do. All you need is to define the item collection of you entities which will be bound to ItemsSource of your DataGrid and a property which will be bound to SelectedItem of your DataGrid . Then in your command you simply reference your selected item property of your model to access the selected item in your DataGrid .

Here is an example implementation with MVVM Light. First you define an observable collection of your entities:

public const string ItemsCollectionPropertyName = "ItemsCollection";
private ObservableCollection<DataItem> _itemsCollection = null;
public ObservableCollection<DataItem> ItemsCollection
{
    get
    {
        return _itemsCollection;
    }
    set
    {
        if (_itemsCollection == value)
        {
            return;
        }

        _itemsCollection = value;
        RaisePropertyChanged(ItemsCollectionPropertyName);
    }
}

Then you define a property to hold the selected item:

public const string SelectedItemPropertyName = "SelectedItem";
private DataItem _selectedItem = null;
public DataItem SelectedItem
{
    get
    {
        return _selectedItem;
    }
    set
    {
        if (_selectedItem == value)
        {
            return;
        }

        _selectedItem = value;
        RaisePropertyChanged(SelectedItemPropertyName);
    }
}

After that you define a command to handle business logic:

private ICommand _doWhateverCommand;
public ICommand DoWhateverCommand
{
    get
    {
        if (_doWhateverCommand == null)
        {
            _doWhateverCommand = new RelayCommand(
                () => { /* do your stuff with SelectedItem here */  },
                () => { return SelectedItem != null; }
            );
        }
        return _doWhateverCommand;
    }
}

Finally you create view elements and bind them to the ViewModel :

<DataGrid ItemsSource="{Binding ItemsCollection}" SelectedItem="{Binding SelectedItem}" AutoGenerateColumns="True" />
<Button Content="Do stuff" Command="{Binding DoWhateverCommand}" />

The question is what is the best and simple way of accessing SelectedItem property of DataGrid from Execute command function in a ViewModel?

Just add a property to the view model class where the ShowOptionsMenuCommand property is defined and bind the SelectedItem property of the DataGrid to this one:

<DataGrid Name="MyGridName" ItemsSource="{Binding Elements}" SelectedItem="{Binding SelectedElement}" ... >

Then you can access the source property ( SelectedElement or whatever you choose to call it) directly from the Execute method.

The other option would be to pass the item as a CommandParameter to the command:

<Button Name="OptionsBtn" ... Content="Options" 
        Command="{Binding ElementName=ElementsViewWindow, Path=DataContext.ShowOptionsMenuCommand}"
        CommandParameter="{Binding}" />

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM