如何调用 UpdateSource() 以在 DataGrid 上进行显式绑定?
How do you call UpdateSource() for explicit binding on a DataGrid?
我有一个 DataGrid,其中包含来自设置对象的信息。当前,DataGrid 和设置对象之间存在双向绑定。但是,我想放置一个 "Save" 按钮,如果用户单击“保存”按钮,它只会将 DataGrid 中所做的更改绑定到对象。但是,我不确定如何使用我的 DataGrid 为我的特定情况调用 UpdateSource()。
这是我的 xaml.cs 代码:
public void LoadDataFields(Data d)
{
Grid1.ItemsSource = d.Fields;
}
private void SaveChanges(object sender, RoutedEventArgs e)
{
BindingExpression be = Grid1.GetBindingExpression(DataGrid.ItemsSourceProperty);
be.UpdateSource();
}
这是我的 xaml 代码:
<DataGrid x:Name="Grid1"
IsReadOnly="False"
Height="360"
Margin="20,15,20,15"
VerticalAlignment="Top"
AutoGenerateColumns="False"
CanUserAddRows="False" SelectionUnit="Cell"
ItemsSource="{Binding data}"
>
<DataGrid.Columns>
<DataGridTemplateColumn Header="Field">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding Path=name, Mode=TwoWay, UpdateSourceTrigger=Explicit}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Length of Field">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding Path=length, Mode=TwoWay, UpdateSourceTrigger=Explicit}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
是否有一种简单的方法来调用 UpdateSource() 以便仅在单击“保存”按钮时才发生绑定?我的猜测是我只是为 GetBindingExpression 方法输入了错误的 属性。
您可以尝试使用以下语法命名您的文本框:
BindingExpression be = tbName.GetBindingExpression(TextBox.TextProperty);
be.UpdateSource();
BindingExpression be2 = tbLength.GetBindingExpression(TextBox.TextProperty);
be2.UpdateSource();
但如果我不想立即应用更改,我会绑定到辅助集合或对象的副本,并应用户请求将更新保存到主列表。当再次修改有界列表、更改、删除或添加项目时,您可以清除辅助列表并重新复制。或者 .. 如果用户可能想要还原更改,请清除有界的更改并从后面复制项目。
是的,有办法,但这不是一个非常非常简单的方法。首先,您需要 2 个辅助方法:
public static T GetVisualChild<T>(Visual parent) where T : Visual
{
Visual visual;
T child = default(T);
int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < childrenCount; i++)
{
visual = (Visual)VisualTreeHelper.GetChild(parent, i);
child = visual as T;
if (child == null)
{
child = GetVisualChild<T>(visual);
}
if (child != null)
{
break;
}
}
return child;
}
public T FindVisualChild<T>(DependencyObject obj, string name) where T : DependencyObject
{
DependencyObject child;
FrameworkElement frameworkElement;
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
child = VisualTreeHelper.GetChild(obj, i);
frameworkElement = child as FrameworkElement;
if (child != null && child is T && frameworkElement != null && frameworkElement.Name == name)
{
return (T)child;
}
else
{
T childOfChild = FindVisualChild<T>(child, name);
if (childOfChild != null)
{
return childOfChild;
}
}
}
return null;
}
然后你必须给你绑定的控件起一个名字。例如 "textBox":
<DataGridTemplateColumn Header="Field">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox x:Name="textBox" Text="{Binding Path=name, Mode=TwoWay, UpdateSourceTrigger=Explicit}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Length of Field">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox x:Name="textBox" Text="{Binding Path=length, Mode=TwoWay, UpdateSourceTrigger=Explicit}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
然后在你的SaveChanges
方法中,你可以使用这个代码:
private void SaveChanges(object sender, RoutedEventArgs e)
{
DataGridRow dataGridRow;
DataGridCellsPresenter dataGridCellsPresenter;
DataGridCell dataGridCell;
TextBox textBox;
BindingExpression bindingExpression;
for (int i = 0; i < Grid1.Items.Count; i++)
{
dataGridRow = (DataGridRow)Grid1.ItemContainerGenerator.ContainerFromIndex(i);
dataGridCellsPresenter = GetVisualChild<DataGridCellsPresenter>(dataGridRow);
for (int j = 0; j < Grid1.Columns.Count; j++)
{
dataGridCell = (DataGridCell)dataGridCellsPresenter.ItemContainerGenerator.ContainerFromIndex(j);
textBox = FindVisualChild<TextBox>(dataGridCell, "textBox");
if (textBox != null)
{
bindingExpression = BindingOperations.GetBindingExpression(textBox, TextBox.TextProperty);
bindingExpression.UpdateSource();
}
}
}
}
希望对您有所帮助
我有一个 DataGrid,其中包含来自设置对象的信息。当前,DataGrid 和设置对象之间存在双向绑定。但是,我想放置一个 "Save" 按钮,如果用户单击“保存”按钮,它只会将 DataGrid 中所做的更改绑定到对象。但是,我不确定如何使用我的 DataGrid 为我的特定情况调用 UpdateSource()。
这是我的 xaml.cs 代码:
public void LoadDataFields(Data d)
{
Grid1.ItemsSource = d.Fields;
}
private void SaveChanges(object sender, RoutedEventArgs e)
{
BindingExpression be = Grid1.GetBindingExpression(DataGrid.ItemsSourceProperty);
be.UpdateSource();
}
这是我的 xaml 代码:
<DataGrid x:Name="Grid1"
IsReadOnly="False"
Height="360"
Margin="20,15,20,15"
VerticalAlignment="Top"
AutoGenerateColumns="False"
CanUserAddRows="False" SelectionUnit="Cell"
ItemsSource="{Binding data}"
>
<DataGrid.Columns>
<DataGridTemplateColumn Header="Field">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding Path=name, Mode=TwoWay, UpdateSourceTrigger=Explicit}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Length of Field">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding Path=length, Mode=TwoWay, UpdateSourceTrigger=Explicit}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
是否有一种简单的方法来调用 UpdateSource() 以便仅在单击“保存”按钮时才发生绑定?我的猜测是我只是为 GetBindingExpression 方法输入了错误的 属性。
您可以尝试使用以下语法命名您的文本框:
BindingExpression be = tbName.GetBindingExpression(TextBox.TextProperty);
be.UpdateSource();
BindingExpression be2 = tbLength.GetBindingExpression(TextBox.TextProperty);
be2.UpdateSource();
但如果我不想立即应用更改,我会绑定到辅助集合或对象的副本,并应用户请求将更新保存到主列表。当再次修改有界列表、更改、删除或添加项目时,您可以清除辅助列表并重新复制。或者 .. 如果用户可能想要还原更改,请清除有界的更改并从后面复制项目。
是的,有办法,但这不是一个非常非常简单的方法。首先,您需要 2 个辅助方法:
public static T GetVisualChild<T>(Visual parent) where T : Visual
{
Visual visual;
T child = default(T);
int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < childrenCount; i++)
{
visual = (Visual)VisualTreeHelper.GetChild(parent, i);
child = visual as T;
if (child == null)
{
child = GetVisualChild<T>(visual);
}
if (child != null)
{
break;
}
}
return child;
}
public T FindVisualChild<T>(DependencyObject obj, string name) where T : DependencyObject
{
DependencyObject child;
FrameworkElement frameworkElement;
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
child = VisualTreeHelper.GetChild(obj, i);
frameworkElement = child as FrameworkElement;
if (child != null && child is T && frameworkElement != null && frameworkElement.Name == name)
{
return (T)child;
}
else
{
T childOfChild = FindVisualChild<T>(child, name);
if (childOfChild != null)
{
return childOfChild;
}
}
}
return null;
}
然后你必须给你绑定的控件起一个名字。例如 "textBox":
<DataGridTemplateColumn Header="Field">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox x:Name="textBox" Text="{Binding Path=name, Mode=TwoWay, UpdateSourceTrigger=Explicit}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Length of Field">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox x:Name="textBox" Text="{Binding Path=length, Mode=TwoWay, UpdateSourceTrigger=Explicit}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
然后在你的SaveChanges
方法中,你可以使用这个代码:
private void SaveChanges(object sender, RoutedEventArgs e)
{
DataGridRow dataGridRow;
DataGridCellsPresenter dataGridCellsPresenter;
DataGridCell dataGridCell;
TextBox textBox;
BindingExpression bindingExpression;
for (int i = 0; i < Grid1.Items.Count; i++)
{
dataGridRow = (DataGridRow)Grid1.ItemContainerGenerator.ContainerFromIndex(i);
dataGridCellsPresenter = GetVisualChild<DataGridCellsPresenter>(dataGridRow);
for (int j = 0; j < Grid1.Columns.Count; j++)
{
dataGridCell = (DataGridCell)dataGridCellsPresenter.ItemContainerGenerator.ContainerFromIndex(j);
textBox = FindVisualChild<TextBox>(dataGridCell, "textBox");
if (textBox != null)
{
bindingExpression = BindingOperations.GetBindingExpression(textBox, TextBox.TextProperty);
bindingExpression.UpdateSource();
}
}
}
}
希望对您有所帮助