示例项目中的按钮和命令有效,但在实际项目中无效

Buttons & Commands in Sample Project Works but not in the real project

我在 WPF DataGrid 中有两个按钮,它们的样式将在运行时更改。

  1. Edit/Save 按钮
  2. Delete/Cancel 按钮

当我点击编辑按钮时,DataGridRow 必须进入编辑模式,两个按钮的样式都应该是:

  1. 保存
  2. 取消

当我单击“保存”或“取消”时,两个按钮都应具有样式:

  1. 编辑
  2. 删除

当我点击删除按钮时,应该不会发生任何样式更改。

我已尝试完成此任务两次:

实际和示例项目

  1. 在我实际申请中(失败)Download
  2. 在示例应用程序中(成功)Download

下面是我实际应用的代码:

(下面只显示了部分必要的代码,完整代码请从上面的链接下载解决方案)

PartyView.xaml

<!--Some Code-->

<DataGridTemplateColumn Header="Edit" Width="50" IsReadOnly="True">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>
                <Button x:Name="btnEdit" Style="{StaticResource ResourceKey=EditButton}" Height="35" Width="35" 
                        Visibility="{Binding DataContext.IsInEdit, ElementName=uc,
                                             Converter={StaticResource boolToVisibilityInverseConverter}}" 
                        Click="EditButton_Click" 
                        Command="{Binding DataContext.EditCommand, ElementName=uc}"/>
                <Button x:Name="btnSave" Grid.Row="1" Style="{StaticResource ResourceKey=SaveButton}" Height="35" Width="35" 
                        Visibility="{Binding DataContext.IsInEdit, ElementName=uc,
                                             Converter={StaticResource boolToVisibilityConverter}}" 
                        Click="SaveButton_Click"
                        Command="{Binding DataContext.SaveCommand, ElementName=uc}"/>
            </Grid>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

<DataGridTemplateColumn Header="Delete" Width="70" IsReadOnly="True">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>
                <Button x:Name="btnDelete" Style="{StaticResource ResourceKey=DeleteButton}" Height="35" Width="35"
                        Visibility="{Binding DataContext.IsInEdit, ElementName=uc,
                                             Converter={StaticResource boolToVisibilityInverseConverter}}" 
                        Command="{Binding DataContext.DeleteCommand, ElementName=uc}"/>
                 <Button x:Name="btnCancel" Grid.Row="1" Style="{StaticResource ResourceKey=CancelButton}" Height="35" Width="35" 
                         Visibility="{Binding DataContext.IsInEdit, ElementName=uc,
                                              Converter={StaticResource boolToVisibilityConverter}}" 
                         Command="{Binding DataContext.CancelCommand, ElementName=uc}"
                         Click="CancelButton_Click"/>
            </Grid>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

<!--Some Code-->

在代码隐藏中:

//Some Code

private void EditButton_Click(object sender, RoutedEventArgs e)
{
    int rowIndex = 0;

    DependencyObject dep = (DependencyObject)e.OriginalSource;
    while (dep != null && !(dep is DataGridCell))
    {
        dep = VisualTreeHelper.GetParent(dep);
    }

    if (dep == null)
        return;
    DataGridRow row = null;
    if (dep is DataGridCell)
    {
        while (dep != null && !(dep is DataGridRow))
        {
            dep = VisualTreeHelper.GetParent(dep);
        }

        row = (DataGridRow)dep;
        rowIndex = FindRowIndex(row);
    }

    while (dep != null && !(dep is DataGrid))
    {
        dep = VisualTreeHelper.GetParent(dep);
    }

    if (dep == null)
        return;

    DataGrid dg = (DataGrid)dep;

    dg.CurrentCell = new DataGridCellInfo(dg.Items[rowIndex], dg.Columns[0]);
    dg.BeginEdit();

    for (int column = 0; column <= dg.Columns.Count - 1; column++)
    {
        if (!(GetDataGridCell(new DataGridCellInfo(dg.Items[rowIndex], dg.Columns[column])).IsReadOnly && GetDataGridCell(new DataGridCellInfo(dg.Items[rowIndex], dg.Columns[column])).IsEditing))
        {
            GetDataGridCell(new DataGridCellInfo(dg.Items[rowIndex], dg.Columns[column])).IsEditing = true;
        }
    }

    var rows = GetDataGridRows(dg);

    foreach (DataGridRow r in rows)
    {
        if (!(r.IsEditing))
        {
            r.IsEnabled = false;
        }
    }
}

private void SaveButton_Click(object sender, RoutedEventArgs e)
{
    int rowIndex = 0;

    DependencyObject dep = (DependencyObject)e.OriginalSource;
    while (dep != null && !(dep is DataGridCell))
    {
        dep = VisualTreeHelper.GetParent(dep);
    }

    if (dep == null)
        return;

    DataGridRow row = null;

    if (dep is DataGridCell)
    {

        while (dep != null && !(dep is DataGridRow))
        {
            dep = VisualTreeHelper.GetParent(dep);
        }

        row = (DataGridRow)dep;
        rowIndex = FindRowIndex(row);

    }

    while (dep != null && !(dep is DataGrid))
    {
        dep = VisualTreeHelper.GetParent(dep);
    }

    if (dep == null)
        return;

    DataGrid dg = (DataGrid)dep;

    dg.CommitEdit(DataGridEditingUnit.Row, true);

    for (int column = 0; column <= dg.Columns.Count - 1; column++)
    {
        if (!(GetDataGridCell(new DataGridCellInfo(dg.Items[rowIndex], dg.Columns[column])).IsReadOnly))
        {
            GetDataGridCell(new DataGridCellInfo(dg.Items[rowIndex], dg.Columns[column])).IsEditing = false;
        }
    }

    var rows = GetDataGridRows(dg);

    foreach (DataGridRow r in rows)
    {
        r.IsEnabled = true;
    }
}

private void CancelButton_Click(object sender, RoutedEventArgs e)
{
    DependencyObject dep = (DependencyObject)e.OriginalSource;

    int rowIndex = 0;

    DataGridRow row = null;

    while (dep != null && !(dep is DataGridRow))
    {
        dep = VisualTreeHelper.GetParent(dep);
    }

    row = (DataGridRow)dep;
    rowIndex = FindRowIndex(row);

    while (dep != null && !(dep is DataGrid))
    {
        dep = VisualTreeHelper.GetParent(dep);
    }

    if (dep == null)
        return;

    DataGrid dg = (DataGrid)dep;

    var rows = GetDataGridRows(dg);

    dg.CancelEdit(DataGridEditingUnit.Row);

    for (int column = 0; column <= dg.Columns.Count - 1; column++)
    {
        if (!(GetDataGridCell(new DataGridCellInfo(dg.Items[rowIndex], dg.Columns[column])).IsReadOnly))
        {
            GetDataGridCell(new DataGridCellInfo(dg.Items[rowIndex], dg.Columns[column])).IsEditing = false;
        }
    }

    foreach (DataGridRow r in rows)
    {
        r.IsEnabled = true;
    }
}

public DataGridCell GetDataGridCell(DataGridCellInfo cellInfo)
{
    var cellContent = cellInfo.Column.GetCellContent(cellInfo.Item);
    if (cellContent != null)
        return (DataGridCell)cellContent.Parent;

    return null;
}

private int FindRowIndex(DataGridRow row)
{
    DataGrid dataGrid = ItemsControl.ItemsControlFromItemContainer(row) as DataGrid;

    int index = dataGrid.ItemContainerGenerator.IndexFromContainer(row);

    return index;
}

public IEnumerable<DataGridRow> GetDataGridRows(DataGrid grid)
{
    var itemsSource = grid.ItemsSource as IEnumerable;
    if (null == itemsSource) yield return null;
    foreach (var item in itemsSource)
    {
        var row = grid.ItemContainerGenerator.ContainerFromItem(item) as DataGridRow;
        if (null != row) yield return row;
    }
}

视图模型:

private bool _isInEdit;
public bool IsInEdit
{
    get
    {
        return _isInEdit;
    }
    set
    {
        _isInEdit = value;
        OnPropertyChanged(() => IsInEdit);
    }
}

private void Edit()
{
    IsInEdit = true;
}

private void Save()
{
    IsInEdit = false;
    SaveToDataBase();
}

private void Cancel()
{
    IsInEdit = false;
}

public void SaveToDataBase()
{
    _partyClient.UpdateParty(SelectedParty);
}

我查看了您出色的示例,发现您的通知实施工作不正常。所以我为了测试你的 ViewModelBase 改为 BindableBase https://github.com/PrismLibrary/Prism/blob/master/Source/Prism/Mvvm/BindableBase.cs 现在它按预期工作了。

编辑: 您的 NotificationObject 不是源自 INotifyPropertyChanged。所以如果添加继承,它也可以正常工作。