2011-06-14 5 views
1

NumericUpDown의 value 속성과 cs 개체의 속성 사이에 데이터 바인딩을 설정하려고합니다. NumericUpDown은 모달 대화 상자에 있으므로 사용자가 확인 버튼을 누르면 데이터 바인딩이 업데이트되기를 원합니다. 이 NumericUpDown은 모달이 아닌 대화 상자 상황에서 제대로 작동하는 PropertyGrid에 있으므로 원래 데이터 바인딩을 만든 XAML을 수정하고 싶지 않습니다. 또한 데이터 바인딩을 변경하기 위해 XAML을 복제하기를 원하지 않습니다. 그래서, 복사 및 모달 대화 상자의로드 된 이벤트 처리기에서 데이터 바인딩을 수정하려면 노력하고있어.UI 요소 데이터가 변경되면 WPF OneTime 데이터 바인딩이 분리됩니다.

여기에서 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를 Explicit으로 변경합니다. 사용자가 NumericUpDown 통해 BindingExpression있는 DataItem의 특성을 목표 값을 변경

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; 
    } 

은 널로 설정 얻는다. 그런 다음 그 BindingExpression 아래 UpdateSource()를 호출하면 "바인딩이 분리되면이 작업을 수행 할 수 없습니다."라는 예외가 발생합니다.

void ApplyClicked(object sender, RoutedEventArgs e) 
{ 
    foreach(BindingExpression express in m_bindings) 
    express.UpdateSource(); 
} 

내가 뭘 잘못하고 있니?

+5

모든 게시물 아래에 "Frigging Code 표시"라는 버튼이 있어야합니다. 나는 지금 당장 그것을 눌러야한다. –

+2

"UI 요소 값을 변경할 때 ..."? 요소의 값을 명시 적으로 수정하면 바인딩이 분리됩니다. 바운드 값을 업데이트한다는 의미입니까? –

+0

예, "UI 요소를 변경합니다"라고 말하면 UI 요소를 통해 바인딩의 대상 값을 수정하고 있음을 의미합니다. – Hank

답변

2

문제점을 발견했습니다. 데이터 바인딩에는 소스를 업데이트하기 위해 TwoWay (또는 OneWayToSource) 모드가 있어야합니다. 따라서 위의 코드에서 OneWay를 TwoWay로 변경하면됩니다.

관련 문제