Я пытаюсь установить привязку данных между свойством value объекта NumericUpDown и свойством объекта CS.NumericUpDown находится в модальном диалоговом окне, поэтому я хочу, чтобы привязка данных обновлялась только тогда, когда пользователь нажимает кнопку ОК.Этот NumericUpDown находится в PropertyGrid, который прекрасно работает в немодальной диалоговой ситуации, поэтому я не хочу изменять XAML, который изначально создал привязку данных.Я также не хочу дублировать XAML, просто чтобы изменить привязку данных.Итак, я пытаюсь скопировать и изменить привязку данных в обработчике событий Loaded для диалогового окна Modal.
Здесь я копирую и изменяю привязку данных, изначально созданную в XAML.
void OnLoad(object sender, RoutedEventArgs e)
{
GetBindings(DialogPropPanel);
}
private void GetBindings(FrameworkElement root)
{
FieldInfo[] infos = root.GetType().GetFields(BindingFlags.Public | BindingFlags.FlattenHierarchy |
BindingFlags.Instance | BindingFlags.Static);
foreach(FieldInfo field in infos)
{
if(field.FieldType == typeof(DependencyProperty))
{
DependencyProperty dp = (DependencyProperty)field.GetValue(null);
BindingExpression ex = root.GetBindingExpression(dp);
if(ex != null)
{
PropertyElement elem = FindBoundElement(ex.DataItem, GroupContainer.PropertyGroups);
if(elem != null)
{
Binding bd = ex.ParentBinding;
if(bd.Mode == BindingMode.Default || bd.Mode == BindingMode.TwoWay)
{
// Copy the binding an change mode.
Binding newBinding = CreateOneTimeBinding(bd, ex.DataItem);
BindingOperations.ClearBinding(root, dp);
BindingOperations.SetBinding(root, dp, newBinding);
BindingExpression nuExp = root.GetBindingExpression(dp);
m_bindings.Add(nuExp);
}
}
}
}
}
int children = VisualTreeHelper.GetChildrenCount(root);
for(int i = 0; i < children; i++)
{
FrameworkElement child = VisualTreeHelper.GetChild(root, i) as FrameworkElement;
if(child != null)
GetBindings(child);
}
}
ЗдесьЯ изменяю режим на OneTime, а UpdateSourceTrigger на явный.
public static Binding CreateOneTimeBinding(Binding binding, object source)
{
var result = new Binding
{
Source = source,
AsyncState = binding.AsyncState,
BindingGroupName = binding.BindingGroupName,
BindsDirectlyToSource = binding.BindsDirectlyToSource,
Converter = binding.Converter,
ConverterCulture = binding.ConverterCulture,
ConverterParameter = binding.ConverterCulture,
//ElementName = binding.ElementName,
FallbackValue = binding.FallbackValue,
IsAsync = binding.IsAsync,
Mode = BindingMode.OneWay,
NotifyOnSourceUpdated = binding.NotifyOnSourceUpdated,
NotifyOnTargetUpdated = binding.NotifyOnTargetUpdated,
NotifyOnValidationError = binding.NotifyOnValidationError,
Path = binding.Path,
//RelativeSource = binding.RelativeSource,
StringFormat = binding.StringFormat,
TargetNullValue = binding.TargetNullValue,
UpdateSourceExceptionFilter = binding.UpdateSourceExceptionFilter,
UpdateSourceTrigger = UpdateSourceTrigger.Explicit,
ValidatesOnDataErrors = binding.ValidatesOnDataErrors,
ValidatesOnExceptions = binding.ValidatesOnExceptions,
XPath = binding.XPath,
};
foreach(var validationRule in binding.ValidationRules)
result.ValidationRules.Add(validationRule);
return result;
}
Когда пользователь изменяет целевое значение через NumericUpDown, свойство DataItem выражения BindingExpression устанавливается равным нулю.Затем, когда я вызываю UpdateSource () ниже для этого BindingExpression, генерируется исключение, которое говорит: «Невозможно выполнить эту операцию, когда привязка отсоединена».
void ApplyClicked(object sender, RoutedEventArgs e)
{
foreach(BindingExpression express in m_bindings)
express.UpdateSource();
}
Что я делаю неправильно?