【问题标题】:Binding a method to a delegate type DependencyProperty将方法绑定到委托类型 DependencyProperty
【发布时间】:2018-04-26 18:27:41
【问题描述】:

在 myUserControl.xaml.cs 我有一个名为“IsExtensionValid”的 bool DependencyProperty,其值由以下几行分配:

    bool a = TargetFile.Extension.MatchFileMask(FileFilters, true);
    bool b = (FileValidator is null) ? true : FileValidator(TargetFile).Item1;
    IsExtensionValid = (a && b);

其中FileFiltersFileValidator 分别是字符串和委托类型DependencyProperty,FileValidator 的委托类型定义为:

    public delegate Tuple<bool, string> ExtraValidation(FileInfo fileInfo);
    public delegate Tuple<bool, string> StaticExtraValidation(FileInfo fileInfo, object o);
    // I also tried this static version with corresponding modifications to the function definition and usages (see below) but still couldn't bind

在mainwindow.xaml.cs中,我定义了一个函数:

    public Tuple<bool, string> ValidateMinFile(FileInfo f) // ExtraValidation delegate
    { return new Tuple<bool, string>(true, "File is invalid"); }
    // meaningful test logic removed but principle stands

在 mainwindow.xaml 我正在尝试通过 xaml 绑定 myUserControlInstance.FileValidator = ValidateMinFile。我尝试了多种方法组合,包括是否使ValidateMinFile 静态、是否作为资源包含、是否作为RelativeSource 引用,以及更多我不记得的方法。我当前的迭代(翻译为人为的示例土地)是:

<local:myUserControl x:Name="MinFileControl"
                       FileFilters="Min Files|*.min"
                       FileValidator="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:}}, Path=ValidateMinFile}"/>

真正的线条实际上是这样的:

<local:FileSelectGroup x:Name="fsgMinFile" DockPanel.Dock="Top" Margin="2"
                       Title="Min file:"
                       FileFilters="Min Files|*.min"
                       PropertyChanged="fsgMinFile_PropertyChanged"
                       FileValidator="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:mainwindow}}, Path=ValidateMinFile}"/>

编辑:我尝试的另一件事是创建一个委托类型作为主窗口的属性并将其设置为引用ValidateMinFile的静态版本

FileSelectGroup.ExtraValidation ValidateMinFileDelegate = ValidateMinFile;`

使用 ValidateMinFile 静态,但是当我在 myUserControl 中访问 FileValidator 的行(带有 bool b = FileValidator... 的行)处断点时,FileValidator 为空。


如何将窗口的本地函数绑定到该窗口中包含的 UserControl 的 DependencyProperty? 或者在这种特殊情况下:如何通过 xaml 设置 myUserControlInstance.FileValidator = ValidateMinFile

【问题讨论】:

  • 我从未听说过委托类型的依赖属性。当然,您不能将其绑定到方法组。你也许可以给你的窗口一个相同委托类型的依赖属性,它返回委托,并绑定它。
  • @EdPlunkett 我确实尝试过,但一无所获(见编辑:)但我可能做错了绑定。
  • @Dammer15 我看到了你的回答——“记住不能绑定到私人”或类似的东西,就在有人投反对票并被删除之前。好点子。将委托属性添加到主窗口时忘记设置 public。

标签: c# wpf data-binding dependency-properties


【解决方案1】:

UserControl1.xaml.cs

public delegate Tuple<bool, string> ExtraValidation(FileInfo fi);

public partial class UserControl1 : UserControl
{
    public UserControl1()
    {
        InitializeComponent();
    }

    #region FileValidator Property
    public ExtraValidation FileValidator
    {
        get { return (ExtraValidation)GetValue(FileValidatorProperty); }
        set { SetValue(FileValidatorProperty, value); }
    }

    public static readonly DependencyProperty FileValidatorProperty =
        DependencyProperty.Register(nameof(FileValidator), typeof(ExtraValidation), typeof(UserControl1),
            new PropertyMetadata(null, FileValidator_PropertyChanged));
    #endregion FileValidator Property

    protected static void FileValidator_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        //  I just put this here for testing: If it's non-null, it'll be called. 
        //  I set a breakpoint in the MainWindow method to detect the call. 
        (d as UserControl1).FileValidator?.Invoke(null);
    }
}

MainWindow.xaml.cs

    public MainWindow()
    {
        InitializeComponent();

        FileValidator = ValidateMinFile;
    }

    #region FileValidator Property
    public ExtraValidation FileValidator
    {
        get { return (ExtraValidation)GetValue(FileValidatorProperty); }
        set { SetValue(FileValidatorProperty, value); }
    }

    public static readonly DependencyProperty FileValidatorProperty =
        DependencyProperty.Register(nameof(FileValidator), typeof(ExtraValidation), typeof(MainWindow),
            new PropertyMetadata(null));
    #endregion FileValidator Property

    public Tuple<bool, string> ValidateMinFile(FileInfo f) // ExtraValidation delegate
    {
        //  Breakpoint here
        return new Tuple<bool, string>(false, "blah");
    }

MainWindow.xaml

    <local:UserControl1
        FileValidator="{Binding FileValidator, RelativeSource={RelativeSource AncestorType=Window}}"
        />

工作正常。

【讨论】:

  • 是的,当我创建委托属性时,我没有使用public。啊!!!我花了太多时间在这上面,并没有看到明显的流血。我会重新测试这个版本,如果我办公室的灯也能正常工作,我会接受。
  • @Still.Tony 那是编程。
  • 我应该将漂亮的单行 c# 版本放在主窗口的构造函数中,但我想完全理解 WPF-y 的做法。
  • @Still.Tony 我同意。掌握绑定的回报是巨大的。
  • @Still.Tony 是的,他们很可怜。我编写了 sn-ps 来创建它们。 sn-ps 会自动将它们放在一个#region 中,我可以将其折叠起来,而不必查看所有的 barf。
猜你喜欢
  • 2011-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-20
  • 2011-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多