【问题标题】:Using a command on a custom control在自定义控件上使用命令
【发布时间】:2011-12-16 12:50:43
【问题描述】:

我正在尝试使用搜索文本框(我按照本教程制作的:http://davidowens.wordpress.com/2009/02/18/wpf-search-text-box/)。

我使用 MVVM 和 WPF。当您在视图的代码隐藏文件中编写“搜索”事件时,上述用户控件有效,但我无法使用命令(使用 ViewModel)。

(当您大约 2 秒没有输入内容时,搜索事件会触发。)

我尝试过使用 Caliburn,因此它可以将视图事件“映射”到 viewmodel 方法。但是,当事件触发时,应用程序崩溃:“找不到方法 SearchText() 的目标。”在自定义用户控件的 RaiseSearchEvent 方法上。

查看以下测试应用程序:Test application

谁能告诉我我做错了什么?我告诉 CaliBurn 执行以下操作:

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

所以我认为这是正确的。这意味着当“Search”事件触发时,caliburn 将在 ViewModel 中查找方法 SearchText。但这不会发生,它会导致我的应用崩溃和烧毁。

你知道为什么吗?或者我如何解决这个问题(不一定要使用 Caliburn)。 我已经尝试添加“扩展命令支持”(http://msdn.microsoft.com/en-us/library/dd458928.aspx),但这对我来说有点太复杂了:/

感谢您的帮助!!

【问题讨论】:

    标签: c# wpf mvvm command caliburn.micro


    【解决方案1】:

    您正在使用 Caliburn 的 ActionMessage,但由于您不使用其 Bootstrapper 类来启动您的应用程序,因此 MainView 的 DataContext 未设置为 MainViewModel 的实例。如果你在运行时检查 SearchTextBox 的 DataContext,你会看到它是空的。

    这里有一系列步骤可以解决您的问题(使用您链接的示例项目)

    创建一个名为 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();
            }
        }
    }
    

    最后,您需要按照华尔街程序员的建议删除括号

    这些步骤应该会导致您的应用实例化您的引导程序,进而将 MainViewModel 实例化为应用程序的根视图模型,然后创建一个 MainView 并将其 DataContext 连接到 MainViewModel。此时,您的应用程序应该可以按预期运行。

    【讨论】:

    • 非常感谢阿德里安!它应该像它应该的那样工作:) 我非常感谢您花时间制定解决方案。我的错误是我假设(看,这就是我出错的地方)引导程序没有做我的 app.xaml 没有做的其他事情,即设置启动窗口。我会记住这一点,因为 CaliBurn 看起来是一个非常方便的工具 :)
    【解决方案2】:

    在我运行您的应用程序后,我发现您需要初始化 MainViewModel 并将 SearchTextBox 的 Text 与 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>
    

    【讨论】:

    • 在使用 Caliburn.Micro 时,您不应在代码隐藏中显式设置视图的数据上下文。如果使用约定,您也不应该要求显式绑定。
    • devdigital 是对的,Caliburn 负责所有这些事情。不过感谢您的兴趣:)
    • @Team-JoKi:哦,我不了解 Caliburn,只是想像一般的 WPF,但是由于我的代码运行良好,这一点告诉你两件事-设置数据上下文和绑定文本-一些东西错误的。抱歉打扰了。
    • 你不必道歉:/我很感激你尝试了
    【解决方案3】:

    删除()

    <cal:ActionMessage MethodName="SearchText" />
    

    【讨论】:

    • 感谢您的回复!不幸的是,我已经尝试过了,但这并不能解决我的问题。您是否尝试运行该示例?
    猜你喜欢
    • 1970-01-01
    • 2011-06-25
    • 2010-12-26
    • 1970-01-01
    • 1970-01-01
    • 2013-10-19
    • 1970-01-01
    • 2012-01-28
    • 2016-12-18
    相关资源
    最近更新 更多