Привязка метода к типу делегата DependencyProperty - PullRequest
0 голосов
/ 26 апреля 2018

В myUserControl.xaml.cs У меня есть bool DependencyProperty с именем IsExtensionValid, значение которого назначается следующими строками:

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

Где FileFilters и FileValidator - это строки и тип делегата 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 Я пытаюсь связать myUserControlInstance.FileValidator = ValidateMinFile через xaml. Я пробовал несколько комбинаций методов, в том числе сделать ValidateMinFile статическими или нет, включать в качестве ресурса или нет, ссылаться на RelativeSource или нет, и еще несколько, которые я не помню. Моя текущая итерация (в переводе на contrived-example-land):

<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 имеет значение null.


Как связать локальную для окна функцию с DependencyProperty UserControl, содержащегося в этом окне? или в данном конкретном случае: Как установить myUserControlInstance.FileValidator = ValidateMinFile через xaml?

1 Ответ

0 голосов
/ 26 апреля 2018

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}}"
        />

Работает нормально.

...