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 数据网格示例
- ToggleButton 不传达更改
- DataGridCheckBoxColumn 效果很好
<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
这是我在这里的第一个问题,请耐心等待。
我很困惑为什么这个 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 数据网格示例
- ToggleButton 不传达更改
- DataGridCheckBoxColumn 效果很好
<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