Datagrid 模板列更新源触发器显式只更新第一行 [英] Datagrid templatecolumn update source trigger explicit only updates first row

查看:21
本文介绍了Datagrid 模板列更新源触发器显式只更新第一行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

我的学生管理类:

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 (I'm actually just testing things out)

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
});

显式更新源的按钮,它只更新第一行而不是所有编辑过的行(请注意,我只是在测试它,这就是我只在一个列上尝试这个的原因):

Button for Explicit UpdateSource that only updates first row instead of all the edited rows (Note that I'm only testing it that's why I only tried this on one column):

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

我从这个人那里得到了 FindChild FindChild

I got the FindChild from this guy FindChild

我和这个人几乎有同样的问题,但没有人回答他的问题:有同样问题的老兄

I pretty much have the same issue with this guy but no one is answering his questions: dude with le same issue

然后我只是通过一个按钮刷新它们:

And then I just refresh them through a button:

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

现在,它有点工作了,我的 updatesourcetrigger 属性设置为显式,因此我可以在单击按钮后保存更改,但只有第一行会更新,还有其他方法可以显式更新 sourcetrigger 属性吗?

Now, it works a bit and my updatesourcetrigger property is set to explicit so I can save changes once I click the button, but only the first row gets updated, are there any other ways to update the sourcetrigger property explicitly?

推荐答案

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

With the help of a small method to find all visual descendants ( = Framework elements instanciated from Template definitions) and some Linq functions to check descendants are textboxes with a given name, you can explicit update the binding for all rows in the Visual Tree.

这里是帮手:

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

在按钮点击时,只需要调用helper:

In the button click, only need to call the helper :

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());
}

应该有帮助,祝你好运

这篇关于Datagrid 模板列更新源触发器显式只更新第一行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆