Поведение команды CheckBox для Silverlight MVVM Pattern - PullRequest
0 голосов
/ 28 апреля 2010

Я пытаюсь определить , когда элемент проверен, и , который элемент проверен в ListBox с использованием Silverlight 4 и инфраструктуры Prism. Я нашел этот пример при создании поведения и попытался следовать ему, но в отладчике ничего не происходит. У меня три вопроса:

  1. Почему моя команда не выполняется?
  2. Как определить, какой элемент был проверен (т.е. передать параметр команды)?
  3. Как мне отладить это? (т.е. где я могу поставить точки останова, чтобы начать входить в это)

Вот мой код:

Вид:

        <ListBox x:Name="MyListBox" ItemsSource="{Binding PanelItems, Mode=TwoWay}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <CheckBox IsChecked="{Binding Enabled}" my:Checked.Command="{Binding Check}"  />
                        <TextBlock x:Name="DisplayName" Text="{Binding DisplayName}"/>
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

ViewModel:

public MainPageViewModel()
{
    _panelItems.Add( new PanelItem
    {
        Enabled = true,
        DisplayName = "Test1"
    } );

    Check = new DelegateCommand<object>( itemChecked );
}

public void itemChecked( object o )
{
//do some stuff
}

public DelegateCommand<object> Check { get; set; }

Класс поведения

public class CheckedBehavior : CommandBehaviorBase<CheckBox>
    {
        public CheckedBehavior( CheckBox element )
            : base( element )
        {
            element.Checked +=new RoutedEventHandler(element_Checked);
        }

        void element_Checked( object sender, RoutedEventArgs e )
        {
            base.ExecuteCommand();
        }               
    }

Командный класс

public static class Checked
{
    public static ICommand GetCommand( DependencyObject obj )
    {
        return (ICommand) obj.GetValue( CommandProperty );
    }

    public static void SetCommand( DependencyObject obj, ICommand value )
    {
        obj.SetValue( CommandProperty, value );
    }

    public static readonly DependencyProperty CommandProperty =
            DependencyProperty.RegisterAttached( "Command", typeof( CheckBox ), typeof( Checked ), new
            PropertyMetadata( OnSetCommandCallback ) );

    public static readonly DependencyProperty CheckedCommandBehaviorProperty =
                DependencyProperty.RegisterAttached( "CheckedCommandBehavior", typeof( CheckedBehavior ), typeof( Checked ), null );

    private static void OnSetCommandCallback( DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e )
    {
        CheckBox element = dependencyObject as CheckBox;
        if( element != null )
        {
            CheckedBehavior behavior = GetOrCreateBehavior( element );
            behavior.Command = e.NewValue as ICommand;
        }
    }
    private static CheckedBehavior GetOrCreateBehavior( CheckBox element )
    {
        CheckedBehavior behavior = element.GetValue( CheckedCommandBehaviorProperty ) as CheckedBehavior;
        if( behavior == null )
        {
            behavior = new CheckedBehavior( element );
            element.SetValue( CheckedCommandBehaviorProperty, behavior );
        }

        return behavior;
    }
    public static CheckedBehavior GetCheckCommandBehavior( DependencyObject obj )
    {
        return (CheckedBehavior) obj.GetValue( CheckedCommandBehaviorProperty );
    }
    public static void SetCheckCommandBehavior( DependencyObject obj, CheckedBehavior value )
    {   
        obj.SetValue( CheckedCommandBehaviorProperty, value );
    }               

}

Ответы [ 2 ]

2 голосов
/ 28 апреля 2010

Твоего образца недостаточно для воспроизведения на моем ПК, но вот что я бы исправил в первую очередь:

  • Привязки в DataTemplate отсутствуют, "Mode = TwoWay", если вы хотите, чтобы свойство Enabled было установлено в вашем PanelItem (- Привязке ItemsSource не требуется Mode = TwoWay, но это второстепенная деталь)
  • DataContext ItemTemplate является экземпляром PanelItem, поэтому привязка команды Check кажется неправильной: в PanelItem отсутствует свойство Check. Привязка должна быть: my: Checked.Command = "{Binding ElementName = MyListBox, Path = DataContext.Check}

Подобные вещи всегда сложно отлаживать. Посмотрите на окно вывода VS; там отображаются ошибки привязки (путь не найден). Когда у вас есть обратный вызов изменения DP (например, OnSetCommandCallback), точка останова сообщит вам, как прошла привязка.

Редактировать: добавлено после 1-го комментария (поскольку я не могу использовать функцию комментариев на ПК, которую я должен использовать сейчас) Свойство Присоединенная команда определено как тип CheckBox в классе Checked, но свойство Check в виртуальной машине является DelegateCommand. Я согласен с WPF в отношении несоответствия типов :-) Объявление свойства выглядит так:

public static readonly DependencyProperty CommandProperty = 
    DependencyProperty.RegisterAttached( 
        "Command", typeof( CheckBox ), 
        typeof( Checked ), new PropertyMetadata( OnSetCommandCallback ) ); 

Вторым параметром должен быть тип свойства, так что я думаю, что-то вроде ICommand в вашем случае.

Из любопытства: в OnSetCommandCallback вас не волнует значение, установленное для свойства Command (которое находится в e.NewValue). Как вы связываете экземпляр CheckedBehavior со свойством Check виртуальной машины?

Редактировать после второго комментария: Нет, второй абзац выше не имеет отношения к вашему вопросу. Может быть, это не имеет смысла. Я не могу понять роль CheckedBehavior.

По поводу вопроса, какой пункт отмечен / не отмечен: что вам нужно более точно? У вас есть экземпляр PanelItem, чье свойство Enabled устанавливается в значение true или false через связывание; таким образом, отмеченные элементы имеют значение Enabled = true.

Редактировать после третьего комментария: Спасибо за объяснение ваших потребностей. Вы на самом деле не используете параметр пути привязки к присоединенному свойству, вы можете написать:

my:Checked.Command="{Binding}"

Таким образом, e.NewValue является связанным PanelItem в OnSetCommandCallback. Таким образом, его можно передать экземпляру CheckedBehavior (в его конструкторе), который может переслать его при вызове Execute of ICommand.

0 голосов
/ 21 октября 2010

CheckBehavior.cs:

public class CheckBehavior : CommandBehaviorBase<CheckBox>
{
    public CheckBehavior(CheckBox element) : base(element)
    {
        element.Checked += OnElementChecked;
        element.Unchecked += OnElementChecked;
    }

    private void OnElementChecked(object sender, RoutedEventArgs e)
    {
        if (sender is CheckBox && ((CheckBox)sender).IsPressed)
        {
            base.ExecuteCommand();
        }
    }
}

CheckCommand.cs:

public class CheckCommand
{
    public static ICommand GetCommand(DependencyObject obj)
    {
        return (ICommand)obj.GetValue(CommandProperty);
    }

    public static void SetCommand(DependencyObject obj, ICommand value)
    {
        obj.SetValue(CommandProperty, value);
    }

    public static object GetCommandParameter(DependencyObject obj)
    {
        return obj.GetValue(CommandParameterProperty);
    }

    public static void SetCommandParameter(DependencyObject obj, object value)
    {
        obj.SetValue(CommandParameterProperty, value);
    }

    public static readonly DependencyProperty CommandProperty =
        DependencyProperty.RegisterAttached("Command", typeof(ICommand), typeof(CheckCommand), new PropertyMetadata(OnSetCommandCallback));

    public static readonly DependencyProperty CommandParameterProperty =
        DependencyProperty.RegisterAttached("CommandParameter", typeof(object), typeof(CheckCommand), new PropertyMetadata(OnSetCommandParameterCallback));

    public static readonly DependencyProperty CheckedCommandBehaviorProperty =
        DependencyProperty.RegisterAttached("CheckedCommandBehavior", typeof(CheckBehavior), typeof(CheckCommand), null);

    private static void OnSetCommandCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
    {
        CheckBox element = dependencyObject as CheckBox;
        if (element != null)
        {
            CheckBehavior behavior = GetOrCreateBehavior(element);
            behavior.Command = e.NewValue as ICommand;
        }
    }

    private static void OnSetCommandParameterCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
    {
        CheckBox element = dependencyObject as CheckBox;
        if (element != null)
        {
            CheckBehavior behavior = GetOrCreateBehavior(element);
            behavior.CommandParameter = e.NewValue;
        }
    }

    private static CheckBehavior GetOrCreateBehavior(CheckBox element)
    {
        CheckBehavior behavior = element.GetValue(CheckedCommandBehaviorProperty) as CheckBehavior;
        if (behavior == null)
        {
            behavior = new CheckBehavior(element);
            element.SetValue(CheckedCommandBehaviorProperty, behavior);
        }

        return behavior;
    }
    public static CheckBehavior GetCheckCommandBehavior(DependencyObject obj)
    {
        return (CheckBehavior)obj.GetValue(CheckedCommandBehaviorProperty);
    }
    public static void SetCheckCommandBehavior(DependencyObject obj, CheckBehavior value)
    {
        obj.SetValue(CheckedCommandBehaviorProperty, value);
    } 
}

И пример:

<CheckBox Commands:CheckCommand.Command="{Binding MyCheckCommand}}"
          Commands:CheckCommand.CommandParameter="{Binding}"/>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...