Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
238 views
in Technique[技术] by (71.8m points)

c# - Datagrid templatecolumn update source trigger explicit only updates first row

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>

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

Sample Code:

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

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;

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.

Here is the helper :

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

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

It should help, good luck


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...