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?
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
来源:https://stackoverflow.com/questions/32736265/datagrid-templatecolumn-update-source-trigger-explicit-only-updates-first-row