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 绑定到 ContentControlDataContextAnswer 属性:

<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>