Datagrid templatecol列更新源触发器显式地只更新第一行

本文关键字:更新 一行 templatecol 触发器 Datagrid | 更新日期: 2023-09-27 18:14:01

My XAML:

<DataGridTemplateColumn Header=" Student ID" Width="Auto">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <TextBox x:Name="StudentIdTextBox"  Text="{Binding Path=StudentID, UpdateSourceTrigger=Explicit, Mode=TwoWay}" PreviewTextInput="ID_OnPreviewTextInput" />
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
我StudentManagementClass

:

public class StudentManagement:INotifyPropertyChanged
{
    private string StudId;
    public bool Check { get; set; }
    public int ID { get; set; }
    public string StudentID
    {
        get { return StudId; }
        set
        {
            StudId = value;
            PropertyChanged(this, new PropertyChangedEventArgs("StudentID"));
        }
    }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Gender { get; set; }
    public string Birthdate { get; set; }
    public string MobileNumber { get; set; }
    public string Year { get; set; }
    public string Section { get; set; }
    public string Department { get; set; }
    public string Course { get; set; }
    public string Semester { get; set; }
    public List<string> AccessLevel { get; set; }
    public string AccessLevels { get; set; }
    public bool SetTime { get; set; }
    public string StartDate { get; set; }
    public string Expiration { get; set; }
    public event PropertyChangedEventHandler PropertyChanged = delegate { };
}

示例代码:

public ObservableCollection<SM> StudentManagements { get; set; }

Temp List(我实际上只是测试出来的东西)

StudentManagements = new ObservableCollection<SM>();
List<string> AccessLevel = new List<string>();
AccessLevel.Add("a");
AccessLevel.Add("b");
AccessLevel.Add("c");
AccessLevel.Add("d");
AccessLevel.Add("e");
StudentManagements.Add(new SM()
{
    StudentID = "1111",
    AccessLevel = AccessLevel,
    AccessLevels = "a,c",
    Birthdate = "1/1/1993",
    Course = "",
    Department = "",
    Expiration = "1/1/1993",
    FirstName = "",
    Gender = "Male",
    LastName = "",
    MobileNumber = "09497740052",
    Section = "",
    Semester = "1st",
    StartDate = "1/1/1993",
    Year = "2nd",
    SetTime = true,
    ID = 1
});
StudentManagements.Add(new SM()
{
    StudentID = "2222",
    AccessLevel = AccessLevel,
    AccessLevels = "e,d",
    Birthdate = "1/1/1992",
    Course = "",
    Department = "",
    Expiration = "1/1/1992",
    FirstName = "",
    Gender = "Male",
    LastName = "",
    MobileNumber = "09497740052",
    Section = "",
    Semester = "1st",
    StartDate = "1/1/1994",
    Year = "2nd",
    SetTime = true,
    ID = 1
});

按钮的显式UpdateSource,只更新第一行,而不是所有编辑的行(请注意,我只是测试它,这就是为什么我只尝试在一列):

x = FindChild<TextBox>(AccessGrid, "StudentIdTextBox");
BindingExpression a = x.GetBindingExpression(TextBox.TextProperty);
a.UpdateSource();

我从这个家伙那里得到FindChild

我对这个家伙也有同样的问题,但是没有人回答他的问题:dude with le same issue

然后我通过按钮刷新它们:

AccessGrid.ItemsSource = null;
AccessGrid.ItemsSource = StudentManagements;

现在,它工作了一点,我的updatesourcetrigger属性被设置为显式的,所以我可以保存更改,一旦我点击按钮,但只有第一行得到更新,有任何其他方法来更新sourcetrigger属性显式?

Datagrid templatecol列更新源触发器显式地只更新第一行

使用一个小方法来查找所有的可视后代(=从模板定义实例化的框架元素)和一些Linq函数来检查后代是否是具有给定名称的文本框,您可以显式地更新可视树中所有行的绑定。

下面是帮助器:

public static class VisualTreeHelperExtension
{
    struct StackElement
    {
        public FrameworkElement Element { get; set; }
        public int Position { get; set; }
    }
    public static IEnumerable<FrameworkElement> FindAllVisualDescendants(this FrameworkElement parent)
    {
        if (parent == null)
            yield break;
        Stack<StackElement> stack = new Stack<StackElement>();
        int i = 0;
        while (true)
        {
            if (i < VisualTreeHelper.GetChildrenCount(parent))
            {
                FrameworkElement child = VisualTreeHelper.GetChild(parent, i) as FrameworkElement;
                if (child != null)
                {
                    if (child != null)
                        yield return child;
                    stack.Push(new StackElement { Element = parent, Position = i });
                    parent = child;
                    i = 0;
                    continue;
                }
                ++i;
            }
            else
            {
                // back at the root of the search
                if (stack.Count == 0)
                    yield break;
                StackElement element = stack.Pop();
                parent = element.Element;
                i = element.Position;
                ++i;
            }
        }
    }
}

在按钮上点击,只需要调用助手:

private void Button_Click(object sender, RoutedEventArgs e)
{
    // to check :
    MessageBox.Show(StudentManagements[1].StudentID.ToString());
    var textboxes = AccessGrid.FindAllVisualDescendants()
        .Where(elt => elt.Name == "StudentIdTextBox" )
        .OfType<TextBox>();
    foreach (var textbox in textboxes)
    {
        BindingExpression binding = textbox.GetBindingExpression(TextBox.TextProperty);
        binding.UpdateSource();
    }
    // to check :
    MessageBox.Show(StudentManagements[1].StudentID.ToString());
}

应该有帮助,祝你好运