问题描述
我的 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 模板列更新源触发器显式只更新第一行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!