2

我遇到绑定问题。由于RelativeSource需要视觉树向上移动并找到所需的祖先,因此您只能在 an 上使用它,UIElement但我正在尝试对RelativeSourceNon-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,我的验证规则也没有参与逻辑或可视树。

问题是我如何使这种情况起作用,如何从非 UIElement(例如我的 ValidationRule)中找到 StackPanel?

我为我的代码没有编译而道歉,但我希望你能理解我想要做什么。我给你们50分的正确答案。

4

1 回答 1

3

您可以执行以下操作:

  1. 创建一个从 Freezable 派生的辅助组件,并为您要绑定的内容定义一个 DependencyProperty。

  2. 创建一个带有属性的 ValidationRule,该属性接受帮助组件的对象,类似于您已经完成的操作。

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

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

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>
于 2013-04-15T20:16:03.043 回答