【问题标题】:Binding a Silverlight control function to my view model将 Silverlight 控件函数绑定到我的视图模型
【发布时间】:2011-12-09 10:53:57
【问题描述】:

好的,我正在使用这些自定义控件。不过不要担心那部分,这个问题与他们的工作无关。

有问题的控件是一个网格(类似于常规网格),它带有一个 BeginInsert 函数,这是向列表中添加新项目的捷径。

现在我想要的是在我的视图模型中访问该方法。目前我确实有这个,但它通过我背后的 XAML 代码,这是我不想要的 - 我希望它直接从 XAML 到视图模型。

目前情况如下:

((UserViewModel)Resources["usersViewModel"]).HydUsersGridBeginInsert = () => this.GridViewData.BeginInsert();

此代码在后面的 XAML 代码中。 HydUsersGridBeginInsert 属于 Action 类型,位于视图模型中。 GridViewData 是网格的名称。

那么我怎样才能把它从我的代码中直接放到我的视图模型中呢?

谢谢。

【问题讨论】:

    标签: silverlight c#-4.0 silverlight-4.0


    【解决方案1】:

    使用事件命令带参数。

     <Button Content="Add">
        <i:Interaction.Triggers>
           <i:EventTrigger EventName="Click">
                <cmd:EventToCommand Command="{Binding AddClickCommand, Mode=OneWay}"
                                            PassEventArgsToCommand="True" />
            </i:EventTrigger>
         </i:Interaction.Triggers>
     </Button>
    

    这里的命名空间“i”指的是 xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" 和

    xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.SL4"

    这是galasoft MVVM轻工具包(谷歌下载)

    在viewModel中添加类似的代码

     public ICommand AddClickCommand { get; set; }
    
     AddClickCommand = new RelayCommand<string>((e) =>
     {
          this.BeginInsert();
     });
    

    希望这对你有用。

    我以为你会从我的回答开始。

    我想说服你的是

        <your:YourGrid x:Name="yourGrid">
         <i:Interaction.Triggers>
             <i:EventTrigger EventName="Loaded">
                 <cmd:EventToCommand Command="{Binding GridLoadedCommand, Mode=OneWay}"
                                            PassEventArgsToCommand="True" />
            </i:EventTrigger>
         </i:Interaction.Triggers>
     </your:YourGrid>
    

    您需要做的就是在 LoadedCommand 中。

     YourGrid grid ;
     public ICommand GridLoadedCommand { get; set; }
    
     GridLoadedCommand = new RelayCommand<RoutedEventHandler>((s, e) =>
     {
         grid = (YourGrid) s;
     });
    
     public ICommand AddClickCommand { get; set; }
    
     AddClickCommand = new RelayCommand<string>((e) =>
     {
          grid.BeginInsert();
     });
    
    
     Now what you say about this.
    

    【讨论】:

    • 感谢您的评论,特别是因为您解释了我需要的东西。当我第一次学习时,我可以使用类似的东西。也就是说,恐怕这个问题还没有在这里得到回答。您向我展示的是如何将事件直接映射到我背后的代码。我已经知道该怎么做(顺便说一句,使用显示的方法)。我正在使用的网格具有附加功能。我在示例中展示的“BeginInsert”函数实际上做了一些事情。我不知道它做了什么,但它做了一些事情。这是我想从我的虚拟机调用的方法。
    • 第二种解决方案让我们更接近,但问题仍然存在。如果我在视图模型中,我不希望将用户元素绑定到它。所以我不能在视图模型中声明用户元素。除此之外,没关系......但它是一个交易破坏者。
    • 如果您不希望 ViewModel 中的 ref 指向 View 中的任何内容,则需要使用消息传递、行为,或者注入某种类型的服务来访问您需要的内容。
    • 如果您正在使用的 Grid 做某事并且您不想在 VM 中引用它,那么您必须通过消息传递来调用它。或使用 MEF 框架。恕我直言,无论哪种方式,您都将在 VM 中调用 BeginInsert() 之前参考网格
    【解决方案2】:

    我相信您想要的是能够从您的 ViewModel 中调用网格上的 BeginEdit?有几种方法可以做到这一点:

    1) 您可以使用消息传递,就像 MVVM-Light 框架中的那样。在您背后的代码中,您将订阅一个事件 BeginEdit,在您的 ViewModel 中,您将发布 BeginEdit 事件。

    2) 你可以创建一个行为,here 是一个类似的例子,其中 TreeView 上的一个节点通过使用一个行为来展开。

    因此,在示例中,您可以设置一个变量 IsBeginEdit,然后行为将触发,在 GridView 上调用 BeginEdit。 sourceMiscView/MiscViewModel

    行为:

    在我列出的示例源中,我使用的是 Caliburn Micro,并且通过命名按钮元素 x:Name="BeginEdit" CM 将自动将其绑定到我的 BeginEdit 方法。如果你使用的是 Mvvm-Light,你可以使用 EventToCommand。

    <Button Content="BeginEdit">
        <i:Interaction.Triggers>
           <i:EventTrigger EventName="Click">
                <cmd:EventToCommand Command="{Binding BeginEdit, Mode=OneWay}"
                                            PassEventArgsToCommand="True" />
            </i:EventTrigger>
         </i:Interaction.Triggers>
     </Button>
    
    [Description("BeginEdit")]
        public class BeginEditBehavior : TargetedTriggerAction<RadGridView>
        {
            private RadGridView _radGridView;
    
            protected override void OnAttached()
            {
                base.OnAttached();
    
                _radGridView = (RadGridView) (AssociatedObject);
            }
    
            protected override void Invoke(object parameter)
            {
                _radGridView.BeginEdit();
            }
        }
    
    View: 
    
    <telerik:RadGridView ItemsSource="{Binding MyItems, Mode=TwoWay}">
                    <i:Interaction.Triggers>
                        <ei:PropertyChangedTrigger Binding="{Binding IsBeginEdit, Mode=TwoWay}">
                            <i:Interaction.Behaviors>
                                <ei:ConditionBehavior>
                                    <ei:ConditionalExpression>
                                        <ei:ComparisonCondition LeftOperand="{Binding IsBeginEdit}"
                                                                RightOperand="True" />
                                    </ei:ConditionalExpression>
                                </ei:ConditionBehavior>
                            </i:Interaction.Behaviors>
                            <framework:BeginEditBehavior />
                        </ei:PropertyChangedTrigger>
                    </i:Interaction.Triggers>
                </telerik:RadGridView>
    

    视图模型:

    private bool _isBeginEdit;
            public bool IsBeginEdit
            {
                get { return _isBeginEdit; }
                set
                {
                    _isBeginEdit = value;
                    NotifyOfPropertyChange(() => IsBeginEdit);
                }
            }
    
            public void BeginEdit()
            {
                IsBeginEdit = true;
            }
    

    3) 可能不是最好的方法,您可以在 ViewModel 中存储对 View 的引用。例如,Caliburn Micro 为您提供了一种从 ViewModel 中访问 View GetView() 的方法,然后您可以获得对网格的引用并调用 BeginEdit()。

    我喜欢选项 2,但选项 1 也可以。

    【讨论】:

    • 能否详细说明第一个选项?
    • 我举个例子。
    • 谢谢。我通读了你给我的第二个选项的链接......老实说,我发现它有点令人困惑。嗯,很混乱。
    • 嗨,德里克。也许你能帮我一个忙,用英语解释一下行为的过程?我的意思是...行为根据 IsBeginEdit 更改的状态激活...但是是什么导致它改变?希望你能帮助我理解这一点。为了记录,在看到这个之前我根本不知道行为。从那以后,我按照教程创建了一个简单的教程,但这远不止于此。提前致谢。
    • 通过命名按钮 BeginEdit,Caliburn Micro 自动将其绑定到方法。如果您使用的是 MVVM-Light,它与 EventToCommand 相同。技术。该按钮实现了 ICommand,因此您也可以使用它。
    猜你喜欢
    • 2011-09-18
    • 2010-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多