Использование команды в пользовательском элементе управления

Я пытаюсь использовать текстовое поле поиска (которое я сделал, следуя этому руководству: http://davidowens.wordpress.com/2009/02/18/wpf-search-text-box/).

Я использую MVVM и WPF. Приведенный выше пользовательский элемент управления работает, когда вы пишете событие «Поиск» в файле кода программной части представления, но я не могу заставить его работать с командой (используя ViewModel).

(Событие поиска срабатывает, когда вы ничего не вводите в течение примерно 2 секунд.)

Я пытался использовать Caliburn, поэтому он может «сопоставить» событие представления с методом модели представления. Однако при возникновении события происходит сбой приложения: «Цель для метода SearchText() не найдена». в методе RaiseSearchEvent из пользовательского элемента управления.

См. следующее тестовое приложение: Тестовое приложение.

Может ли кто-нибудь сказать мне, что я делаю неправильно? Я сказал CaliBurn сделать следующее:

<i:Interaction.Triggers>
        <i:EventTrigger EventName="Search">
            <cal:ActionMessage MethodName="SearchText()" />
        </i:EventTrigger>
</i:Interaction.Triggers>

Так что я считаю, что это правильно. Это означает, что когда срабатывает событие «Поиск», caliburn будет искать метод SearchText в ViewModel. Однако этого не происходит, и это приводит к сбою и сгоранию моего приложения.

Ты знаешь почему? Или как я мог решить эту проблему (не обязательно с Caliburn). Я уже пытался добавить «Расширение поддержки команд» (http://msdn.microsoft.com/en-us/library/dd458928.aspx), но для меня это слишком сложно :/

Спасибо за любую помощь!!


person Team-JoKi    schedule 27.10.2011    source источник


Ответы (3)


Вы используете ActionMessage Caliburn, но поскольку вы не используете его класс Bootstrapper для запуска своего приложения, DataContext MainView не установлен на экземпляр MainViewModel. Если вы проверите DataContext SearchTextBox во время выполнения, вы увидите, что он равен нулю.

Вот ряд шагов, которые могут решить вашу проблему (используя связанный пример проекта)

Создайте класс с именем MyBootstrapper. Это должно выглядеть так

public class MyBootstrapper : Bootstrapper<MainViewModel> {}

Добавьте новый загрузчик в коллекцию ресурсов приложения, как показано ниже (App.xaml).

<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:WpfApplicationParadise"
             x:Class="WpfApplicationParadise.App">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary>
                    <local:MyBootstrapper x:Key="bootstrapper" />
                </ResourceDictionary>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

Не знаю почему, но если загрузчик не вложен в мою сборку, он никогда не создается при запуске App.InitializeComponent()...

Измените App.xaml.cs, чтобы он просто запускал InitializeComponent. Обратите внимание, что мне пришлось немного подправить вашу сборку, чтобы она заработала... InitializeComponent() определяется в файле App.g.cs только в том случае, если у вас есть вложенный словарь ресурсов из шага 2 или если у вас есть x: Атрибут имени в App.xaml или, возможно, что-то еще...

using System.Windows;

namespace WpfApplicationParadise
{
    public partial class App : Application
    {
        public App()
        {
            InitializeComponent();
        }
    }
}

Наконец, вам нужно удалить скобки, как предложил Wallstreet Programmer.

Эти шаги должны привести к тому, что ваше приложение создаст экземпляр вашего загрузчика, который, в свою очередь, создаст экземпляр MainViewModel в качестве корневой модели представления вашего приложения, а затем создаст MainView и подключит его DataContext к MainViewModel. В этот момент ваше приложение должно работать так, как ожидалось.

person Adrian    schedule 27.10.2011
comment
Спасибо большое Адриан! Он работает так, как должен :) Я очень ценю, что вы нашли время, чтобы найти решение. Моя ошибка заключалась в том, что я предполагал (видите, вот где я ошибся), что загрузчик не делал ничего другого, чего не делал мой app.xaml, то есть устанавливал окно запуска. Я запомню это, потому что CaliBurn выглядит как настоящий удобный инструмент :) - person Team-JoKi; 28.10.2011

Удалять ()

<cal:ActionMessage MethodName="SearchText" />
person Wallstreet Programmer    schedule 27.10.2011
comment
Спасибо за ответ! К сожалению, я уже пробовал это, это не решает проблему для меня. Вы пробовали запустить пример? - person Team-JoKi; 27.10.2011

После запуска вашего приложения я вижу, что вам нужно инициализировать MainViewModel, а также связать текст SearchTextBox с TekstBoxTekst.

Отделенный код

public partial class MainView : Window
{
    public MainView()
    {
        InitializeComponent();
        this.Loaded += (s, e) =>
                        {
                            this.DataContext = new MainViewModel();
                        };
    }
}

XAML

<StackPanel>
    <l:SearchTextBox 
        Text="{Binding TekstBoxTekst, UpdateSourceTrigger=PropertyChanged}"
        Height="24" x:Name="TekstBoxTekst" Margin="145,144,145,143">
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="Search">
                <cal:ActionMessage MethodName="SearchText">
                </cal:ActionMessage>
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </l:SearchTextBox>
</StackPanel>
person Jin-Wook Chung    schedule 27.10.2011
comment
Вы не должны явно задавать контекст данных представления в отделенном коде при использовании Caliburn.Micro. Вы также не должны требовать явных привязок при использовании соглашений. - person devdigital; 27.10.2011
comment
devdigital прав, Caliburn позаботится обо всем этом. Хотя спасибо за интерес :) - person Team-JoKi; 27.10.2011
comment
@Team-JoKi: О, я не знаю Caliburn и просто подумал, как обычный WPF, но поскольку мой код работает хорошо, этот пункт говорит вам о двух вещах: настройках контекста данных и тексте привязки - что-то не так. Извините за беспокойство. - person Jin-Wook Chung; 27.10.2011
comment
Вам не нужно извиняться :/ Я благодарен, что вы попытались - person Team-JoKi; 27.10.2011