InvokeCommandAction CommandParameter всегда ноль - PullRequest
0 голосов
/ 08 ноября 2018

Справочная информация. Я пытаюсь включить и отключить команду в зависимости от того, выделено ли текстовое поле или нет.

Согласно моим исследованиям, мне нужно использовать триггеры событий. Либо действие InvokeCommandAction, о котором эта проблема, либо действие InvokeMethodAction, которое по какой-то причине не существует в моей системе.

Проблема: я настроил эту программу следующим образом. Он запускается, команды запускаются, но параметры всегда равны нулю.

<Window x:Class="LogWpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
        xmlns:local="clr-namespace:LogWpfApp"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <local:ViewModel />
    </Window.DataContext>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <Button Grid.Row="0" Grid.Column="0" Content="Copy" HorizontalAlignment="Left" Margin="0,0,0,0" VerticalAlignment="Top" Width="75"
                Command="{Binding CmdCopy}" CommandTarget="{Binding ElementName=textBoxNote}" CommandParameter="{Binding ElementName=textBoxNote}"/>
        <Button Grid.Row="0" Grid.Column="1" Content="Paste" HorizontalAlignment="Left" Margin="0,0,0,0" VerticalAlignment="Top" Width="75"
                />
        <TextBox x:Name="textBoxNote" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Margin="0,0,0,0" TextWrapping="Wrap"
                 Text="{Binding Note}">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="SelectionChanged">
                    <i:InvokeCommandAction Command="{Binding CmdSelectionLengthChanged}" CommandParameter="{Binding ElementName=textBoxNote, Path=SelectionLength}" />
                    <i:InvokeCommandAction Command="{Binding CmdSelectionStartChanged}" CommandParameter="{Binding ElementName=textBoxNote, Path=SelectionStart}" />
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </TextBox>
        <Label Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" Content="{Binding Clipboard}"/>
    </Grid>
</Window>

А вот ViewModel:

public class ViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private RelayCommand<TextBox, TextBox> cmdCopy;
    private RelayCommand<object, object> cmdPaste = new RelayCommand<object, object>(foo => { }, (tb) => { return true; });
    private RelayCommand<int, int> cmdSelectionLengthChanged;
    private RelayCommand<int, int> cmdSelectionStartChanged;
    private String note = "This is some default initial text";
    private String clippboard = "";
    private int selectionLength = 0;
    private int selectionStart = 0;



    public ViewModel()
    {
        cmdCopy = new RelayCommand<TextBox, TextBox>(
            tb => { clippboard = tb.SelectedText; },
            tb => { return SelectionLength > 0; /* tb != null && tb.SelectionLength > 0;*/ }
        );

        cmdSelectionLengthChanged = new RelayCommand<int, int>(
            length => {
                Console.WriteLine("New SelectionLength {0}", length);
                SelectionLength = length; cmdCopy.FireCanExecuteChanged(); },
            foo => { return true; }
        );

        cmdSelectionStartChanged = new RelayCommand<int, int>(
            start => {
                Console.WriteLine("New SelectionStart {0}", start);
                selectionStart = start; },
            foo => { return true; }
        );
    }



    public RelayCommand<TextBox, TextBox> CmdCopy => cmdCopy;
    public RelayCommand<object, object> CmdPaste => cmdPaste;
    public RelayCommand<int, int> CmdSelectionLengthChanged => cmdSelectionLengthChanged;
    public RelayCommand<int, int> CmdSelectionStartChanged => cmdSelectionStartChanged;


    public String Note
    {
        get { return note; }
        set
        {
            if (this.note != value)
            {
                this.note = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Note)));
            }
        }
    }

    public String Clipboard
    {
        get { return clippboard; }
        private set
        {
            if (clippboard != value)
            {
                clippboard = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Clipboard)));
            }
        }
    }

    public int SelectionLength
    {
        get { return selectionLength; }
        set
        {
            if (selectionLength != value)
            {
                selectionLength = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SelectionLength)));
            }
        }
    }
}

1 Ответ

0 голосов
/ 08 ноября 2018

Ни SelectionLength, ни SelectionStart не являются свойствами зависимостей, которые вызывают уведомления, когда они установлены. Это означает, что значения параметров вашей команды всегда будут иметь начальные значения 0.

Если вы связываетесь с TextBox:

<i:InvokeCommandAction Command="{Binding CmdSelectionLengthChanged}" CommandParameter="{Binding ElementName=textBoxNote}" />

... вы сможете получить значения, явно запросив свойства в ваших Execute методах:

cmdSelectionLengthChanged = new DelegateCommand<TextBox, TextBox>(
    textBox => {
                   Debug.WriteLine("New SelectionLength {0}", textBox.SelectionLength);
               },
    foo => { return true; }
);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...