【问题标题】:Validating WPF dynamically created framework element验证 WPF 动态创建的框架元素
【发布时间】:2017-02-02 15:22:46
【问题描述】:

我正在创建一个由动态创建的控件组成的窗口。我正在使用 ItemsControl 创建它们:

<ItemsControl Grid.Row="0" Name="DynamicContent" ItemsSource="{Binding Path=EmbeddedInputControls}" ItemTemplateSelector="{Binding Path=EmbeddedInputControlsTemplateSelector}">
      <ItemsControl.ItemsPanel>
          <ItemsPanelTemplate>
              <WrapPanel Orientation="Horizontal"/>
          </ItemsPanelTemplate>
     </ItemsControl.ItemsPanel>
</ItemsControl>

ItemTemplateSelector 根据资源类型选择DataTemplate

<Window.Resources>
  <converters:ErrorBooleanToBrush x:Key="ErrorBooleanToBrush"/>
  <DataTemplate x:Key="EmbeddedStringInput" DataType="embeddedInputDescriptors:StringEmbeddedInputDescriptor">
      <StackPanel Orientation="Horizontal" Background="{Binding IsErrored, Converter={StaticResource ErrorBooleanToBrush}}">
         <Label Content="{Binding LabelContent}"></Label>
         <dxe:TextEdit EditValue="{Binding TextValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" IsReadOnly="{Binding IsReadOnly}" />
      </StackPanel>
   </DataTemplate>
   <DataTemplate x:Key="EmbeddedIntegerInput" DataType="embeddedInputDescriptors:IntegerEmbeddedInputDescriptor">
        <StackPanel Orientation="Horizontal" Name="IntStackPanel">
            <Label Content="{Binding LabelContent}"></Label>
            <dxe:SpinEdit Value="{Binding IntValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" IsReadOnly="{Binding IsReadOnly}"
                      MinValue="{Binding MinValue}" MaxValue="{Binding MaxValue}" Validate="OnValidate" Tag="{Binding Self}"/>
        </StackPanel>
    </DataTemplate>
</Window.Resources>

这对于显示效果很好,但验证已被证明是一件令人头疼的事情。我终于找到的解决方案使用代码隐藏和OnValidate 事件处理程序:

private void OnValidate(object sender, ValidationEventArgs e)
{
    var dynamicInputElement=((FrameworkElement)sender).Tag as IEmbeddedInputDescriptor;

    var errorContent = dynamicInputElement?.ErrorContent(e.Value);

    if(!string.IsNullOrEmpty(errorContent))
     {
        e.IsValid = false;
        e.ErrorContent = errorContent;
     }
}

这是我必须编写的唯一代码隐藏,我想摆脱它,但我无法看到没有它如何实现验证。验证规则将基于业务逻辑,因此我不能将它们包含在 XAML 中。当我给每个 DataTemplate 一个样式,其成员是从关联的描述符中获取的,但它有点难看时,我几乎得到了一个解决方案:

{Binding IsErrored, Converter={StaticResource ErrorBooleanToBrush}}
<StackPanel.Style>
   <Style>
     <Style.Triggers>
         <DataTrigger Binding="{Binding Path=IsErrored}" Value="True">
               <Setter Property="StackPanel.Background" Value="LightCoral">
                    </Setter>
         </DataTrigger>
      </Style.Triggers>
    </Style>
</StackPanel.Style>

用于派生框架元素的对象是:

internal interface IEmbeddedInputDescriptor
{
    bool IsReadOnly { get; }
    bool IsRequired { get; }
    object Value { get; }
    bool IsErrored { get; }
    string ErrorContent(object value);
}

摆脱代码隐藏会很好,我相信我会在这个过程中学到更多关于 WPF 的有用的东西。

更多信息:重新绑定验证:

<dxe:SpinEdit Value="{Binding IntValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidationRules={Binding valRules}}"

public IEnumerable<ValidationRule> valRules
{
    get { throw new NotImplementedException(); }
}

导致错误“无法在“ValidationRuleCollection”集合中使用“绑定”。 “绑定”只能在 DependencyObject 的 DependencyProperty 上设置。'。

IDataErrorInfo 也有问题。无论我是在主视图模型中还是在描述符本身中实现它,我都没有设法调用任何一个属性。我应该做到这一点的一个可能问题是如何识别错误属性,因为我怀疑它总是“值”,这是模棱两可的。事实上,大多数解决方案都存在问题,那些产生了我可以响应的事件的解决方案让我没有工作的上下文。

这就是我当前的解决方案使用 Tag 属性的原因。否则,很难将表单事件链接回底层业务对象。

【问题讨论】:

  • 我想您可能正在寻找Binding.ValidationRules。您可以在DataTemplates 中进行设置。仍然有 C# 代码,但它以 MVVMish 的方式被考虑在内。您还可以查看IDataErrorInfo,它将验证放在视图模型中。
  • "I broke the example code!" 好的。 “而且现在不行了!”是的,这是通常的结果。还有什么可以帮助你的吗?
  • 嗯?你现在有什么建议?比起阅读无意义的帖子,我还有更好的事情要做。
  • 我在 MSDN 上链接了示例代码。您发布了一些奇怪的 ValidationRules 代码,这些代码不可能工作,而且示例中肯定没有。我什至不明白你对IDataErrorInfo 的反对;没有一个类有不止一个名为Value(或其他任何东西)的属性。无论如何,没有人可以在没有看到代码的情况下帮助您。
  • 我正在使用几个基类,底部的基类确实有一个“值”属性。因此,在尝试识别已修改的内容时,被告知“价值”已更改是模棱两可的。

标签: c# wpf validation


【解决方案1】:

答案与我实现描述符类(成为每个创建的框架元素的数据上下文的对象)的方式有关。我在“错误”基类上实现了 IDataErrorInfo,这意味着在类层次结构中不可见。经过一夜好眠后,我的眼睛焕然一新,几乎立刻就发现了它。

经常这样。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多