简体   繁体   中英

WPF PRISM MVVM get selected item from grid control

I have a DevExpress Grid Control. I want to enable/disable a button based on the selected rows in the grid control, ie, if any rows are selected in the grid control then this button should be enabled. Following is my GridControl code:

<dxg:GridControl x:Name="gridFloorplans" Grid.Column="1" Grid.Row="1" AutoGenerateColumns="None" 
            ItemsSource="{Binding FloorplanList.Result.View}"
            SelectedItems="{Binding SelectedFloorplan,Mode=TwoWay}"
            dx:ThemeManager.Theme="Default" SelectionMode="Row">
        <dxg:GridControl.View>
            <dxg:TableView AllowGrouping="False" ShowGroupPanel="False" AllowEditing="False"  ShowDataNavigator="True" DataNavigatorButtons="Navigation" />
        </dxg:GridControl.View>
        <dxg:GridControl.Columns>
            <dxg:GridColumn FieldName="Name" Header="Floorplan Name" Fixed="Left" />
            <dxg:GridColumn FieldName="Season"  Fixed="Left" />
            <dxg:GridColumn FieldName="Version"  Fixed="Left" />                
        </dxg:GridControl.Columns>            
</dxg:GridControl>

Following is my ViewModel code:

private ObservableCollection<FloorplanData> _selectedFloorplan;

public FloorplanSearchViewModel(IErrorHandlerService inErrorHandler, INavigationService inNavigationService, 
            ISpaDataAdapter inDataAdapter, IAuthorizationService inAuthService)
{            
    // Set the commands
    this.ShowStoreSetCommand = new DelegateCommand<IList<object>>(this.ShowStoreSet, this.CanShowStoreSet);
    this.SearchFloorplansCommand = new DelegateCommand(this.SearchFloorplans);
    this.ShowStatusChangeCommand = new DelegateCommand<IList<object>>(this.ShowStatusChange, this.CanShowStatusChange);

    // Set up the default values for the search
    this.StatusList = new List<object>();
    this.StatusList.Add(Enum.GetName(typeof(FloorplanData.FloorplanStatus), FloorplanData.FloorplanStatus.Pending));
    this.StatusList.Add(Enum.GetName(typeof(FloorplanData.FloorplanStatus), FloorplanData.FloorplanStatus.Review));

    //Initiate the SelectedFloorplan property
    //SelectedFloorplan = new ObservableCollection<FloorplanData>();
}



public ObservableCollection<FloorplanData> SelectedFloorplan
{
    get
    {
        return _selectedFloorplan;
    }
    set
    {
        _selectedFloorplan = value;
        this.ShowStatusChangeCommand.RaiseCanExecuteChanged();
    }
}

public NotifyTaskCompletion<CollectionViewSource> FloorplanList
{
    get;
    private set;
}

private void ShowStatusChange(IList<object> inFloorplans)
{
    try
    {
        // Create the navigation output
        NavigationParameters args = new NavigationParameters();
        args.Add(FloorplanStatusChangeViewModel.PARAM_FLOORPLAN_ID_LIST, GetFloorplanIdList(inFloorplans));
        _navigationService.NavigateTo<Views.FloorplanStatusChangeView>(args);
    }
    catch (Exception ex)
    {
        _errorHandler.HandleError(ex);
    }
}

private bool CanShowStatusChange(IList<object> inFloorplans)
{
    // Check security to see if the current user is allowed to enter the status change screen
    if (_authService.GetAccessLevel(1470) > AuthorizationLevel.None)
    {
        if (SelectedFloorplan!=null)
            return true;
        else
            return false;
    }
    else
    {
        return false;
    }
}

Following is the xaml code for the button:

<Button Margin="4,2" Content="Status Change"  Command="{Binding ShowStatusChangeCommand}" 
                    CommandParameter="{Binding SelectedItems, ElementName=gridFloorplans}">
                <Button.Style>
                    <Style TargetType="Button">
                        <Setter Property="ToolTip" Value="Open the Floorplan Status Change view for the selected floorplans" />
                        <Style.Triggers>
                            <Trigger Property="IsEnabled" Value="False">
                                <Setter Property="ToolTip" Value="You do not have access to open the Floorplan Status Change view" />
                            </Trigger>
                            <DataTrigger 
                                Binding ="{Binding ElementName=gridFloorplans, Path=SelectedFloorplan}" 
                                Value="-1">
                                <Setter Property="Button.IsEnabled" Value="false"/>
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </Button.Style>
            </Button>

How can I enable/disable ShowStatus button based on whether any row is selected in the grid or not?

//You are not using `inFloorplans` parameter within your method body
//Need not pass this parameter
private bool CanShowStatusChange(IList<object> inFloorplans)

Same as CanShowStatusChange method create a property and bind it to the Button which you want to enable/disable

public bool CanShowStatusChange
{
  get
  {  
    if (_authService.GetAccessLevel(1470) > AuthorizationLevel.None)
    {
        if (SelectedFloorplan!=null)
            return true;
        else
            return false;
    }
    else
    {
        return false;
    }
  }
}

Selected floor plan cant be an observable collection. The name detotes its a It denotes a single object. So

private FloorplanData _selectedFloorplan;
public FloorplanData SelectedFloorplan
{
  get
  {
   return _selectedFloorplan;
  }
  set
  {
    _selectedFloorplan = value;
    NotifyPropertyChanged("SelectedFloorplan");
     //or its equivalent method to notify the change
    NotifyPropertyChanged("CanShowStatusChange");
     //or its equivalent method to notify the change of CanShowStatusChange.
  }
}

Make sure you bind SelectedFloorplan property and CanShowStatusChange property in your UI so that they are updated.

1) IsEnabled will get bool value from CanShowStatusChange, so you dont need style.

2) You have grid`s selected items in VM, so why pass it via parameter?

<Button Margin="4,2" Content="Status Change" Command="{Binding ShowStatusChangeCommand}">
    <Button.Style>
        <Style TargetType="Button">
            <Setter Property="ToolTip" Value="Open the Floorplan Status Change view for the selected floorplans" />
            <Style.Triggers>
                <Trigger Property="IsEnabled" Value="False">
                    <Setter Property="ToolTip" Value="You do not have access to open the Floorplan Status Change view" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </Button.Style>
</Button>

3) You set SelectedFloorplan ones, then you just change items in collection! It means than we should subscribe on CollectionChanged

public FloorplanSearchViewModel(IErrorHandlerService inErrorHandler, INavigationService inNavigationService, 
            ISpaDataAdapter inDataAdapter, IAuthorizationService inAuthService)
{            
    // Set the commands
    this.ShowStoreSetCommand = new DelegateCommand<IList<object>>(this.ShowStoreSet, this.CanShowStoreSet);
    this.SearchFloorplansCommand = new DelegateCommand(this.SearchFloorplans);
    this.ShowStatusChangeCommand = new DelegateCommand<IList<object>>(this.ShowStatusChange, this.CanShowStatusChange);

    // Set up the default values for the search
    this.StatusList = new List<object>();
    this.StatusList.Add(Enum.GetName(typeof(FloorplanData.FloorplanStatus), FloorplanData.FloorplanStatus.Pending));
    this.StatusList.Add(Enum.GetName(typeof(FloorplanData.FloorplanStatus), FloorplanData.FloorplanStatus.Review));

    //Initiate the SelectedFloorplan property
    SelectedFloorplan = new ObservableCollection<FloorplanData>();
    SelectedFloorplan.CollectionChanged += SelectedFloorplanOnCollectionChanged;
}


private void SelectedFloorplanOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs)
{
    this.ShowStatusChangeCommand.RaiseCanExecuteChanged();
}


public ObservableCollection<FloorplanData> SelectedFloorplan
{
    get
    {
        return _selectedFloorplan;
    }
    set
    {
        _selectedFloorplan = value;
        this.ShowStatusChangeCommand.RaiseCanExecuteChanged();
    }
}

4) And

private bool CanShowStatusChange()
{
    // Check security to see if the current user is allowed to enter the status change screen
    if (_authService.GetAccessLevel(1470) > AuthorizationLevel.None)
    {
        if (SelectedFloorplan!=null && SelectedFloorplan.Any())
            return true;
        else
            return false;
    }
    else
    {
        return false;
    }
}

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