Использование пользовательского класса в XAML, чтобы его свойства служили местом назначения привязки

Прежде всего извините за мой "пиджин" английский, :(

Приложение построено по шаблону MVVM. ViewModel раскрывает свою функциональность через команды и имеет специальную команду - DispatchCommand, которая получает (в параметре команды) пару других команд/параметров и выполняет полученную команду с полученным параметром. Особенностью (довольно неважной для темы) является то, что DispatcherCommand выполняется в основном потоке приложения, другие команды ViewModel (вызываемые DispatcherCommand) являются асинхронными, и каждая из них выполняет свой делегат Execute() в отдельном потоке. Такой подход (непрямое выполнение асинхронных команд ViewModel через DispatchCommand) используется для управления внутренним состоянием ViewModel (например, DispatchCommands отказывает в вызове конкретной асинхронной команды, пока выполняется другая асинхронная команда и т. д.).

В коде это выглядит так:

// Dispatcher command
public class DispatcherCommand : ICommand { }

// async command
public interface IAsyncCommand : ICommand { }
public class AsyncCommand : IAsyncCommand { }

// view model
public class AsyncModel
{
    public DispatcherCommand Dispatcher { get {...} }

    // async commands - current model capabilities
    public AsyncCommand FirstCapability { get {...} }
    public AsyncCommand SecondCapability { get {...} }
    ...
}

// using example
AsyncModel model = new AsyncModel();
model.Dispatcher.Execute( 
   new { Command = model.FirstCapability, Parameter = "string param" });

Я хочу предоставить доступ к асинхронным командам в XAML таким же образом:

<Button Command="{Binding Path=DispatcherCommand}">
    <Button.CommandParameter>
        <local:CurrentCommandParameters Command="{Binding Path=FirstCapability}"
                                        Parameter="string param"/>
    </Button.CommandParameter>Use first capability</Button>

где

    // DispatcherCommand parameter class
public class DispatcherCommandParameters : DependencyObject
{
    // target async command
    public IAsyncCommand Command
    {
        set { SetValue(CommandProperty, value); }
        get { return (IAsyncCommand)GetValue(CommandProperty); }
    }

    // its parameter
    public object Parameter
    {
        set { SetValue(ParameterProperty, value); }
        get { return GetValue(ParameterProperty); }
    }

    public static readonly DependencyProperty CommandProperty;
    public static readonly DependencyProperty ParameterProperty;

    static CurrentCommandParameters()
    {
        CommandProperty = DependencyProperty.Register("Command",
            typeof(IAsyncCommand),
            typeof(CurrentCommandParameters),
            new PropertyMetadata());

        ParameterProperty = DependencyProperty.Register("Parameter",
            typeof(object),
            typeof(CurrentCommandParameters),
            new PropertyMetadata());
    }
}

но это не работает. DispatcherCommand.Execute(параметр объекта) получает экземпляр класса DispatcherCommandParameters, но его свойство Command равно null.

Что можно сделать в этой ситуации?


В конструкторе окна та же привязка, что и в xaml, успешно создана:

<Button Name="StupidButton" Command="{Binding Path=DispatcherCommand}">

...

public MainWindow()
{
    InitializeComponent();

    // set up data context
    AsyncModel model = new AsyncModel();
    this.DataContext = model;

    // set up binding
    DispatcherCommandParameters dcp = new DispatcherCommandParameters();
    dcp.Parameter = "string parameter value set in code";
    Binding myBinding = new Binding("FirstCapability");
    myBinding.Source = model;
    BindingExpressionBase be = BindingOperations.SetBinding(dcp, 
        DispatcherCommandParameters.CommandProperty, myBinding);
    StupidButton.CommandParameter = dcp;            

    // now when "StupidButton" is pressed, 
    // DispatcherCommand.Execute(object parameter)
    // receives correct reference to AsyncModel.FirstCapability command in 
    // ((DispatcherCommandParameters)parameter).Command property
}

person JSP    schedule 30.08.2010    source источник


Ответы (1)


Если «Команда» имеет значение null в ваших DispatcherCommandParameters, это, скорее всего, просто проблема привязки, есть ли какие-либо предупреждения в вашем окне вывода в Visual Studio?

person JoshVarga    schedule 31.08.2010
comment
К сожалению, в окне вывода нет предупреждений. - person JSP; 31.08.2010