绑定非UIElement

时间:2013-04-08 12:35:28

标签: wpf binding uielement

我遇到了Binding问题。由于RelativeSource需要可视化树向上移动并找到所需的祖先,因此您只能在UIElement上使用它,但我正在尝试对非RelativeSource绑定UIElement,例如ValidationRule,你们都知道它不在VisualTree内,也不在UIElement内。正如您所料,绑定会中断。无法找到RelativeSource因为我说没有VisualTreeLogicalTree可用。我需要让它工作。

以下是XAML的一个示例:

<StackPanel DataContext{Binding}>
  <Grid>
    <ContentControl Content{Binding MVPart1>
      <TextBox>
       <TextBox.Text>
        <Binding Path="VMPart1Property1">
         <Binding.ValidationRules>
           <my:MyValidationRule>
            <my:ValidationRule.DOC>
             <my:DepObjClass DepProp={Binding Path=DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type StackPanel}}}/>
            </my:ValidationRule.DOC>
          </Binding.ValidationRules>
         </Binding>
       </TextBox.Text>
      </TextBox>  
    </ContentControl>
  </Grid>
</StackPanel>

所以基本上MyValidationRule派生自ValidationRule类,但那不是UIElement,也不是DependencyObject,因此我必须创建一个派生自DependencyObject的类,名为DepObjClass,以便能够记下xaml绑定表达式。

这是代码:

public class MyValidationRule : ValidationRule
{
  public DepObjClass DOC
  {
    get;
    set;
  }

  public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
  {
      string text = value as string;
      if (!string.IsNullOrEmpty(text))
      {
         return new ValidationResult(true, string.Empty);
      }

      return new ValidationResult(false, "Not working blahhh");
   }
}

public class DepObjClass : DependencyObject
{
  public object DepProp
  {
    get
    {
      return (object)GetValue(DepPropProperty);
    }
    set
    {
      SetValue(DepPropProperty, value);
    }
  }

  public static DependencyProperty DepPropProperty
     = DependencyProperty.Register(typeof(object), typeof(DepObjClass)......);
}

现在总结一下。 MyValidatonRule不是UIElement而不是DependencyObject,但它有一个类型的属性,因此xaml绑定表达式编译的原因。

当我运行应用程序时,绑定本身无法正常工作,因为无法找到StackPanel,因为ValidationRule没有VisualTree,也没有我的验证规则参与逻辑或Visual Tree。

问题是如何使这样的案例工作,如何从非UIElement中找到StackPanel,例如我的ValidationRule?

我道歉我的代码没有加入,但我希望你能理解我想要做的事情。 我给你们50分给出正确答案。

1 个答案:

答案 0 :(得分:3)

您可以执行以下操作:

  1. 创建一个派生自Freezable的帮助程序组件,并为要绑定的内容定义DependencyProperty。

  2. 创建一个ValidationRule,其中包含一个获取辅助组件对象的属性,类似于您已经完成的操作。

  3. 在对象的Resources中声明一个helper组件的实例,该实例可以绑定到您想要绑定的任何内容。 Freezable及其派生类继承了声明其资源的任何控件的绑定上下文(逻辑树中的位置),因此您可以创建绑定。

  4. 在声明ValidationRule时,使用{StaticResource}将帮助程序组件分配给ValidationRule中的属性。 StaticResource在没有绑定上下文的情况下工作,只要资源在使用之前声明即可。

  5. XAML看起来像这样:

    <StackPanel>
      <StackPanel.Resources>
        <my:Helper x:Key="helper" ValProperty="{Binding}"/>
      </StackPanel.Resources>
      <Grid>
          <TextBox DataContext="{Binding MVPart1}">
           <TextBox.Text>
            <Binding Path="VMPart1Property1">
             <Binding.ValidationRules>
               <my:MyValidationRule Helper="{StaticResource helper}"/>
              </Binding.ValidationRules>
             </Binding>
           </TextBox.Text>
          </TextBox>  
      </Grid>
    </StackPanel>