首页 > 解决方案 > Wpf 绑定 Observablecollection 和 RelayCommand

问题描述

我在将 RelayCommand 绑定到数据网格中的按钮时遇到问题,并且已经将 ItemSource 绑定到 ObservableCollection。

我的问题是 RelayCommand (RemoveCommand) 不可见,无法从 viewmodel 执行。

<Button Grid.Column="0" Style="{StaticResource MaterialDesignFloatingActionMiniDarkButton}" 
                    ToolTip="Remove" 
                    Command="{Binding Path=RemoveCommand}">
                        <materialDesign:PackIcon Kind="Close" Height="24" Width="24" />
                    </Button>

只有可见的东西是来自以前的 ItemSource Binding 的类中的方法,如 IconName 等

<WindowsControl:DataGrid ItemsSource="{Binding ListOfExcelFiles ,IsAsync=True,Mode=TwoWay}"

但我想使用 viewmodel 中的 RelayCommand 可以以某种方式执行此操作,或者我需要重写我的代码?

视图模型:

private ObservableCollection<ExcelFile> _listOfExcelFiles;
public ObservableCollection<ExcelFile> ListOfExcelFiles
{
get { return _listOfExcelFiles; }
set
{
    _listOfExcelFiles = value;
    OnPropertyChanged();
}
}

模型:

 public class ExcelFile :  INotifyPropertyChanged 
    {
        string _name;
        string _filePath;
        string _iconName = "File";
        string _validationIcon = "";
        bool _showbutton = false;

        public bool ShowButton
        {
            get { return _showbutton; }
            set
            {
                _showbutton = value;
                OnPropertyChanged();
            }
        }
        public string IconName
        {
            get { return _iconName; }
            set
            {
                _iconName = value;
            }
        }
        public string Name
        {
            get { return _name; }
            set
            {
                _name = value;
            }
        }
        public string FilePath
        {
            get { return _filePath; }
            set
            {
                _filePath = value;
            }
        }       

        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }

我的 XAML:

    <WindowsControl:DataGrid ItemsSource="{Binding ListOfExcelFiles 
    ,IsAsync=True,Mode=TwoWay}" 
    AutoGenerateColumns="False" 
    Grid.Column="0" Grid.Row="0" 
    SelectionMode="Single" 
    SelectionUnit="FullRow" 
    CanUserAddRows="false" 
    SelectedItem="{Binding SelectedItem, Mode=TwoWay}">
    <DataGrid.Columns>
        <DataGridTemplateColumn Header="Icon" CellStyle="{StaticResource CenteredCell}">
            <DataGridTemplateColumn.CellTemplate >
                <DataTemplate >
                    <materialDesign:PackIcon Kind="{Binding IconName}" 
                    Height="24" Width="24" />
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTextColumn Header="FileName"  
        Width="*" IsReadOnly="True" 
        CellStyle="{StaticResource CenteredLeftCell}" >
            <DataGridTextColumn.Binding>
                <Binding Path="Name" 
                NotifyOnTargetUpdated="True" 
                UpdateSourceTrigger="PropertyChanged" 
                Mode="TwoWay">
                </Binding>
            </DataGridTextColumn.Binding>
        </DataGridTextColumn>
        <DataGridTextColumn Header="FilePath" 
        Binding="{Binding FilePath}" 
        Width="*" IsReadOnly="True" 
        CellStyle="{StaticResource CenteredLeftCell}"></DataGridTextColumn>
        <DataGridTemplateColumn CellStyle="{StaticResource CenteredCell}" Width="*">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <Grid Visibility="{Binding ShowButton,Converter={StaticResource BoolToVisibility},FallbackValue=Hidden}">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*"></ColumnDefinition>
                            <ColumnDefinition Width="*"></ColumnDefinition>
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="*"></RowDefinition>
                        </Grid.RowDefinitions>
                        <Button Grid.Column="0" Style="{StaticResource MaterialDesignFloatingActionMiniDarkButton}" 
                        ToolTip="Remove" 
                        Command="{Binding Path=RemoveCommand}">
                            <materialDesign:PackIcon Kind="Close" Height="24" Width="24" />
                        </Button>
                    </Grid>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</WindowsControl:DataGrid>

标签: c#wpfxamlmvvm

解决方案


在 Binding 中使用带 FindAncestor 的 RelativeSource 并引用 DataGrid 的 DataContext(...您的 ViewModel)

Command={Binding Path=DataContext.RemoveCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}

RelativeSource 使绑定在应用提供的路径之前搜索提供的类型的祖先。


推荐阅读