Datagrid 中文本框上的 C# Wpf 绑定不更新
C# Wpf Binding on Textbox in Datagrid doesn't update
为了我的工作,我需要通过隐藏代码生成数据网格。数据网格包含 2 列:问题(只是文本,不应编辑)和需要基于枚举的文本框或组合框的“答案”。
我尝试将问题列表(包含文本和答案字段)绑定到数据网格。问题栏工作得很好。但是文本框没有任何价值。我可以输入它们,但是一旦我对数据网格进行排序,所有值都消失了。在数据网格的项目源中,我可以看到值根本没有更新:/
这次失败后,我在 XAML 中尝试使用普通数据网格,但它也不起作用。答案列是 DataGridTemplate 列。
这是我的 xaml:
<Window x:Class="BindingTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:BindingTest"
xmlns:t="clr-namespace:BindingTest;assembly=BindingTest"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<DataTemplate x:Key="AnswerTemp">
<ContentControl>
<ContentControl.Style>
<Style TargetType="ContentControl">
<Style.Triggers>
<DataTrigger Binding="{Binding Typ}" Value="{x:Static t:QuestionType.Numeric}">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBox Text="{Binding Path=Answer,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</DataTemplate>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<DataGrid x:Name="MetaDataGrid" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Questions" Binding="{Binding Text}">
</DataGridTextColumn>
<DataGridTemplateColumn Header="Answers" CellTemplate="{StaticResource ResourceKey=AnswerTemp}"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
后面的代码:
// Just contains a Dictionary <string,QuestionBlock> called SeperatorList
public static ActualPage actualPage = new ActualPage();
public MainWindow()
{
InitializeComponent();
QuestionBlock seperator = new QuestionBlock();
seperator.Questions = new ObservableCollection<Question>();
for (int counter = 1; counter < 11; counter++)
seperator.Questions.Add(new Question() { Text = $"What is the {counter}. Answer?", Answer = $"{5 + counter}", Typ = QuestionType.Numeric, Names = new List<string>() { "1", "2", "3" } });
actualPage.SeperatorList.Add("Test", seperator);
MetaDataGrid.ItemsSource = seperator.Questions;
}
问题块中的代码:
public class QuestionBlock : INotifyPropertyChanged
{
private ObservableCollection<Question> _questionBlock;
public event PropertyChangedEventHandler PropertyChanged;
public ObservableCollection<Question> Questions
{
get => _questionBlock;
set
{
_questionBlock = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Questions)));
}
}
}
问题代码:
public class Question : INotifyPropertyChanged
{
private string _text;
private string _answer;
private QuestionType _typ;
public event PropertyChangedEventHandler PropertyChanged;
public string Text
{
get => _text;
set
{
_text = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Text)));
}
}
public string Answer
{
get => _answer;
set
{
_answer = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Answer)));
}
}
public QuestionType Typ
{
get => _typ;
set
{
_typ = value;
}
}
}
我在这里做错了什么?注意:应包含在组合框中的值不是枚举值!有来自字符串列表的值。任何帮助将不胜感激:)
您应该将可编辑控件放在列的 CellEditingTemplate
中:
<DataGridTemplateColumn Header="Answers" CellEditingTemplate="{StaticResource AnswerTemp}">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Answer}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
...并将 TextBox
绑定到 ContentControl
的 DataContext
的 Answer
属性:
<DataTemplate x:Key="AnswerTemp">
<ContentControl>
<ContentControl.Style>
<Style TargetType="ContentControl">
<Style.Triggers>
<DataTrigger Binding="{Binding Typ}" Value="{x:Static t:QuestionType.Numeric}">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBox Text="{Binding Path=DataContext.Answer,
RelativeSource={RelativeSource AncestorType=ContentControl}}"/>
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</DataTemplate>
为了我的工作,我需要通过隐藏代码生成数据网格。数据网格包含 2 列:问题(只是文本,不应编辑)和需要基于枚举的文本框或组合框的“答案”。
我尝试将问题列表(包含文本和答案字段)绑定到数据网格。问题栏工作得很好。但是文本框没有任何价值。我可以输入它们,但是一旦我对数据网格进行排序,所有值都消失了。在数据网格的项目源中,我可以看到值根本没有更新:/
这次失败后,我在 XAML 中尝试使用普通数据网格,但它也不起作用。答案列是 DataGridTemplate 列。
这是我的 xaml:
<Window x:Class="BindingTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:BindingTest"
xmlns:t="clr-namespace:BindingTest;assembly=BindingTest"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<DataTemplate x:Key="AnswerTemp">
<ContentControl>
<ContentControl.Style>
<Style TargetType="ContentControl">
<Style.Triggers>
<DataTrigger Binding="{Binding Typ}" Value="{x:Static t:QuestionType.Numeric}">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBox Text="{Binding Path=Answer,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</DataTemplate>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<DataGrid x:Name="MetaDataGrid" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Questions" Binding="{Binding Text}">
</DataGridTextColumn>
<DataGridTemplateColumn Header="Answers" CellTemplate="{StaticResource ResourceKey=AnswerTemp}"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
后面的代码:
// Just contains a Dictionary <string,QuestionBlock> called SeperatorList
public static ActualPage actualPage = new ActualPage();
public MainWindow()
{
InitializeComponent();
QuestionBlock seperator = new QuestionBlock();
seperator.Questions = new ObservableCollection<Question>();
for (int counter = 1; counter < 11; counter++)
seperator.Questions.Add(new Question() { Text = $"What is the {counter}. Answer?", Answer = $"{5 + counter}", Typ = QuestionType.Numeric, Names = new List<string>() { "1", "2", "3" } });
actualPage.SeperatorList.Add("Test", seperator);
MetaDataGrid.ItemsSource = seperator.Questions;
}
问题块中的代码:
public class QuestionBlock : INotifyPropertyChanged
{
private ObservableCollection<Question> _questionBlock;
public event PropertyChangedEventHandler PropertyChanged;
public ObservableCollection<Question> Questions
{
get => _questionBlock;
set
{
_questionBlock = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Questions)));
}
}
}
问题代码:
public class Question : INotifyPropertyChanged
{
private string _text;
private string _answer;
private QuestionType _typ;
public event PropertyChangedEventHandler PropertyChanged;
public string Text
{
get => _text;
set
{
_text = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Text)));
}
}
public string Answer
{
get => _answer;
set
{
_answer = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Answer)));
}
}
public QuestionType Typ
{
get => _typ;
set
{
_typ = value;
}
}
}
我在这里做错了什么?注意:应包含在组合框中的值不是枚举值!有来自字符串列表的值。任何帮助将不胜感激:)
您应该将可编辑控件放在列的 CellEditingTemplate
中:
<DataGridTemplateColumn Header="Answers" CellEditingTemplate="{StaticResource AnswerTemp}">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Answer}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
...并将 TextBox
绑定到 ContentControl
的 DataContext
的 Answer
属性:
<DataTemplate x:Key="AnswerTemp">
<ContentControl>
<ContentControl.Style>
<Style TargetType="ContentControl">
<Style.Triggers>
<DataTrigger Binding="{Binding Typ}" Value="{x:Static t:QuestionType.Numeric}">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBox Text="{Binding Path=DataContext.Answer,
RelativeSource={RelativeSource AncestorType=ContentControl}}"/>
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</DataTemplate>