WPF MVVM:单击时 Datagrid 模板 ToggleButton 不与模型通信

WPF MVVM: Datagrid Template ToggleButton not communicating with Model when clicked

这是我在这里的第一个问题,请耐心等待。

我很困惑为什么这个 ToggleButton 列在切换时没有将更改传达给已审核的 Match 模型 属性:

<ToggleButton    
    Height="auto" Foreground="White" Margin="0, 0, 10, 0"
    IsChecked="{Binding Reviewed, Mode=TwoWay}">      
</ToggleButton>

但是,此列可以很好地与已审核的匹配模型进行通信属性

<DataGridCheckBoxColumn Header="Test" Width="auto" Binding="{Binding Reviewed, Mode=TwoWay}"/>

我将 post 一些基本代码来帮助理解我的问题。

XAML 数据网格示例

<DataGrid ItemsSource="{Binding Path=ListOfBestMatches}" x:Name="DataGrid_Matches" Height="auto" Width="Auto" Margin="0,0,-4,0" VerticalAlignment="Top" HorizontalAlignment="Stretch" AutoGenerateColumns="False">
                    <!-- Column Headers -->
                    <DataGrid.Columns>                   
                        <DataGridTemplateColumn Header="Reviewed">
                            <DataGridTemplateColumn.CellTemplate>
                                <DataTemplate>
                                    <ToggleButton                                         
                                        Height="auto" Foreground="White" Margin="0, 0, 10, 0"
                                        IsChecked="{Binding Reviewed, Mode=TwoWay}">     
                                    </ToggleButton>
                                </DataTemplate>
                            </DataGridTemplateColumn.CellTemplate>
                        </DataGridTemplateColumn>

                        <DataGridCheckBoxColumn Header="Test" Width="auto" Binding="{Binding Reviewed, Mode=TwoWay}"/>

                    </DataGrid.Columns>
</DataGrid>

ViewModel

public class MainWindowViewModel : BaseViewModel 
{
        /// <summary>
        /// Property/field which holds the official list of best matches and bound to a datagrid
        /// </summary>
        private ObservableCollection<Match> _listOfBestMatches;
        public ObservableCollection<Match> ListOfBestMatches
        {
            get => _listOfBestMatches;
            set
            {
                if (_listOfBestMatches != value)
                {
                    _listOfBestMatches = value;
                    this.OnPropertyChanged("ListOfBestMatches");
                }
            }
        }
}

型号

public class Match : BaseViewModel
{
        /// <summary>
        /// Property which represents the state of the Check Toggle Box in the Best Matches Data grid Reviewed column
        /// </summary>
        private bool reviewed;
        public bool Reviewed
        {
            get { return reviewed; }
            set 
            {                
                    reviewed = value;
                    OnPropertyChanged("Reviewed");

                    Debug.WriteLine("=== SET REVIEWED ===");

            }
        
        }
}

基本视图模型

namespace UserFolders.ViewModels
{

    /// <summary>
    /// This is the base view model which all other view models will extend from.
    /// This model is necesarry for notifying the UI when data has changed so it 
    /// can display appropriately on its own
    /// </summary>
    public class BaseViewModel : INotifyPropertyChanged
    {
        protected void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }
}

终于找到了您的问题的解决方案。我想,问题在于如何更新数据网格单元格。例如,我添加了一些文本列并想知道,它们只会在数据网格单元格失去焦点后立即更新。 UpdateSourceTrigger=PropertyChanged(以前用过,但是这些东西很容易忘记^^)成功了。

这是更改后的代码以及用于测试的文本列:

   <DataGrid ItemsSource="{Binding Path=ListOfBestMatches}" x:Name="DataGrid_Matches" Height="auto" Width="Auto" Margin="0,0,-4,0" VerticalAlignment="Top" HorizontalAlignment="Stretch" AutoGenerateColumns="False"
               >
        <!-- Column Headers -->
                  
        <DataGrid.Columns>
            <DataGridTextColumn Header="name"  Binding="{Binding Name, UpdateSourceTrigger=PropertyChanged}" />
            <DataGridTextColumn Header="name"  Binding="{Binding Name, UpdateSourceTrigger=PropertyChanged}" />
            <DataGridTemplateColumn Header="Reviewed">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <ToggleButton                                         
                                    Height="auto" Foreground="White" Margin="0, 0, 10, 0"
                                    IsChecked="{Binding Reviewed, UpdateSourceTrigger=PropertyChanged}">
                        </ToggleButton>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>

            <DataGridCheckBoxColumn Header="Test" Binding="{Binding Reviewed, UpdateSourceTrigger=PropertyChanged}"/>

        </DataGrid.Columns>
    </DataGrid>

您只需要在您的虚拟机中添加对应的属性(或删除):

private string name;
public string Name
{
    get { return name; }
    set
    {
        name = value;
        OnPropertyChanged("Name");
    }
}

顺便说一句:如果您有兴趣,我前段时间为一门课程制作了一个 MVVM 模式示例项目。它显示了 ViewModelBase class 的一些更新示例以及其他一些内容。您可以在这里找到它:https://github.com/TheRealRolandDeschain/DesignPatternsMVVMExample