Datagrid 模板列更新源触发器显式仅更新第一行
Datagrid templatecolumn update source trigger explicit only updates first row
我的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; }
临时列表(我实际上只是在测试)
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
});
仅更新第一行而不是所有已编辑行的显式更新源按钮(请注意,我只是在测试它,这就是为什么我只在一列上尝试此操作的原因):
x = FindChild<TextBox>(AccessGrid, "StudentIdTextBox");
BindingExpression a = x.GetBindingExpression(TextBox.TextProperty);
a.UpdateSource();
我从这个人那里得到了 FindChild FindChild
我几乎和这个人有同样的问题,但没有人回答他的问题:dude with le same issue
然后我通过一个按钮刷新它们:
AccessGrid.ItemsSource = null;
AccessGrid.ItemsSource = StudentManagements;
现在,它有点工作了,我的 updatesourcetrigger 属性 设置为显式,所以我可以在单击按钮后保存更改,但只有第一行得到更新,还有其他方法可以更新sourcetrigger 属性 明确?
借助查找所有视觉后代的小方法(= 从模板定义实例化的框架元素)和一些检查后代是否为具有给定名称的文本框的 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;
}
}
}
}
在按钮点击时,只需要调用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());
}
应该有帮助,祝你好运
我的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; }
临时列表(我实际上只是在测试)
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
});
仅更新第一行而不是所有已编辑行的显式更新源按钮(请注意,我只是在测试它,这就是为什么我只在一列上尝试此操作的原因):
x = FindChild<TextBox>(AccessGrid, "StudentIdTextBox");
BindingExpression a = x.GetBindingExpression(TextBox.TextProperty);
a.UpdateSource();
我从这个人那里得到了 FindChild FindChild
我几乎和这个人有同样的问题,但没有人回答他的问题:dude with le same issue
然后我通过一个按钮刷新它们:
AccessGrid.ItemsSource = null;
AccessGrid.ItemsSource = StudentManagements;
现在,它有点工作了,我的 updatesourcetrigger 属性 设置为显式,所以我可以在单击按钮后保存更改,但只有第一行得到更新,还有其他方法可以更新sourcetrigger 属性 明确?
借助查找所有视觉后代的小方法(= 从模板定义实例化的框架元素)和一些检查后代是否为具有给定名称的文本框的 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;
}
}
}
}
在按钮点击时,只需要调用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());
}
应该有帮助,祝你好运