Ссылочный элемент управления XAML и свойства в x: Array - PullRequest
0 голосов
/ 07 сентября 2010
<RichTextBox x:Name="OrigText" Margin="0,0,8,0" d:LayoutOverrides="Width"/>
    <Button x:Name="OrigFileBrowse" Command="{Binding BrowseCommand}" CommandParameter="{Binding ElementName=OrigText, Path=Document}" HorizontalAlignment="Center" Margin="0,0,8,2.442" Width="75" Content="Browse" Grid.Row="1" d:LayoutOverrides="Height"/>
    <RichTextBox x:Name="ModifiedText" Grid.Column="1" Margin="8,0,0,0"/>
    <Button x:Name="ModifiedFileBrowse" Command="{Binding BrowseCommand}" CommandParameter="{Binding ElementName=ModifiedText, Path=Document}" HorizontalAlignment="Center" Width="75" Content="Browse" Grid.Row="1" Grid.Column="1" Margin="0,0,0,2.442" d:LayoutOverrides="Height"/>
    <Button x:Name="Compare" Command="{Binding CompareCommand}" HorizontalAlignment="Center" VerticalAlignment="Top" Width="75" Content="Compare" Grid.Row="2" Grid.ColumnSpan="2">
        <Button.CommandParameter>
            <x:Array Type="RichTextBox">
                <local:CompareTextView/>
            </x:Array>
        </Button.CommandParameter>
    </Button>

Попытка получить 2 элемента, которые будут переданы при нажатии кнопки «Сравнить», поскольку тогда будет выполнена команда сравнения.Попытка использовать MultiBinding, однако, запускается при создании экземпляра, и, следовательно, преобразователь затем запускается соответствующим образом.Он НЕ срабатывает, когда я нажимаю кнопку сравнения и выполняется команда сравнения.

Поскольку это не работает, я пытаюсь теперь ссылаться на элементы управления в XAML, чтобы передать их в ArrayExtension.Не уверен в синтаксисе или если это вообще возможно, так как я знаю, что вы не можете связать в ArrayExtension.Вышеприведенное не помогает, так как не может создать новое представление CompareTextView, у которого нет конструктора по умолчанию, так как я использую Prism ...

Довольно расстраивает, надеюсь, кто-то может мне помочь ...

РЕДАКТИРОВАТЬ:

Хотите прояснить некоторые вещи.Проблема не в том, что я хочу, чтобы CanExecute вызывался снова.Проблема в том, что при создании экземпляров элементов управления вызывается и выполняется преобразователь, а значения возвращаются ... но куда они идут, я понятия не имею?Преобразователь больше не вызывается.Если бы я мог получить начальные ссылки на FlowDocument, это было бы спорным вопросом ... но он не возвращает ничего нигде как таковой ... так как это команда ... если это имеет смысл ... при созданиииспользование MultiBinding.

        <Button x:Name="Compare" Command="{Binding CompareCommand}" HorizontalAlignment="Center" VerticalAlignment="Top" Width="75" Content="Compare" Grid.Row="2" Grid.ColumnSpan="2">
        <Button.CommandParameter>
            <MultiBinding Converter="{StaticResource FlowDocumentConverter}">
                <Binding ElementName="OrigText" Path="Document"/>
                <Binding ElementName="ModifiedText" Path="Document"/>
            </MultiBinding>
        </Button.CommandParameter>
    </Button>

ОБНОВЛЕНИЕ:

Попробовав, что упоминает рефери здесь , прокрутите немного вниз, чтобы увидеть его публикацию.Хотя CanExecute постоянно срабатывает, это ничего не решает.Кроме того, я переключил MultiBinding, чтобы он был единичным, он возвращается в ноль.Опять же, когда преобразователь запускается при создании экземпляра, ссылки FlowDocument находятся там ...

ОТВЕТ:

Упоминание Абэ о том, что он кэшируется, заставило меня попробовать что-то еще.Поскольку я знал, что ссылки на FlowDocument были доступны, когда вызывался конвертер, я знал, что они были там.Что-то запуталось.Ключевая часть, кажется, находится в самом конвертере.Я просто возвращал объект [].Затем, когда команда сработала, arg действительно был объектом [], но эти два элемента были нулевыми.Я создал класс с именем Docs, у которого было два свойства, по одному для каждой ссылки FlowDocument.Когда преобразователь сработал, я установил свойства соответствующим образом, а затем возвратил объект Docs.Теперь, когда я инициировал команду сравнения, объект Docs был аргументами, и он имел ссылку на FlowDocuments так, как мне было нужно!Не уверен, что это так, но тот факт, что предметы теряются при использовании объекта [], не имеет смысла для меня.

1 Ответ

2 голосов
/ 08 сентября 2010

Правильный способ сделать это действительно с MultiBinding на CommandParameter. Вы не увидите, как он вызовет ваш метод CanExecute, если WPF не проинформирован о том, что метод может вернуть значение, отличное от того, которое он уже кэшировал (через событие CanExecuteChanged).

Поскольку вы полагаетесь на параметр, переданный для определения этого, мы должны вызвать событие при изменении параметра. Поскольку мы не можем точно определить это в команде, мы можем использовать другой метод: указать WPF опрашивать нашу команду каждый раз, когда она опрашивает UICommands. Это делается путем реализации вашего ICommand следующим образом:

public class MyCommand : ICommand
{
    public void Execute(object parameter) { /* do stuff */ }
    public bool CanExecute(object parameter { /* determine if we can do stuff */ }

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }
}

Очевидно, что это мешает вам использовать Prism DelegateCommand, но это будет реагировать на изменения параметров команды.

UPDATE

Еще одна вещь, которую следует учитывать, это то, что свойство Document на RichTextBox фактически не меняется. Вместо этого, когда вы вводите текст, содержимое FlowDocument изменяется. Поскольку экземпляры свойств не меняются, преобразователь не будет запущен снова, а первоначально преобразованное значение будет сохранено в свойстве CommandParameter.

Один из способов принудительного вызова преобразователя - добавить Binding к MultiBinding, привязанному к свойству, которое будет меняться каждый раз, когда текст RichTextBox изменения.

Несколько хакерским решением было бы использование свойства IsKeyboardFocusWithin, поскольку оно будет имитировать поведение привязки по умолчанию TextBox.Text (т.е. когда TextBox теряет фокус, обновления Binding):

<MultiBinding Converter="{StaticResource FlowDocumentConverter}">
    <Binding ElementName="OrigText" Path="Document" />
    <Binding ElementName="ModifiedText" Path="Document" />
    <Binding ElementName="OrigText" Path="IsKeyboardFocusWithin" />
    <Binding ElementName="ModifiedText" Path="IsKeyboardFocusWithin" />
</MultiBinding>

Очевидно, что в вашем преобразователе вам нужно будет игнорировать эти дополнительные значения, так как они не имеют отношения к вашему преобразованию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...