如何从后面的代码访问我的ViewModel

时间:2014-07-20 03:30:04

标签: c# wpf mvvm

我不明白如何创建命令来创建MVVM可点击矩形。这是我的代码:

<Rectangle x:Name="Color01" Fill="#FFF4F4F5" HorizontalAlignment="Left" Height="100" Margin="10,29,0,0" Stroke="Black" VerticalAlignment="Top" Width="100" MouseDown="Color_MouseDown" />
<Rectangle x:Name="Color02" Fill="#FFF4F4F5" HorizontalAlignment="Left" Height="100" Margin="115,29,0,0" Stroke="Black" VerticalAlignment="Top" Width="100"/>
<Rectangle x:Name="Color03" Fill="#FFF4F4F5" HorizontalAlignment="Left" Height="100" Margin="220,29,0,0" Stroke="Black" VerticalAlignment="Top" Width="100"/>
<Rectangle x:Name="Color04" Fill="#FFF4F4F5" HorizontalAlignment="Left" Height="100" Margin="325,29,0,0" Stroke="Black" VerticalAlignment="Top" Width="100"/>

在我的第一个矩形上,你可以看到我在事件后面创建了一个代码。首先,我不知道如何从后面的代码访问我的ViewModel。其中两个并不是MVVM。

public partial class MainWindow : Window
{
    /// <summary>
    /// Initializes a new instance of the MainWindow class.
    /// </summary>
    public MainWindow()
    {
        InitializeComponent();
        Closing += (s, e) => ViewModelLocator.Cleanup();
    }

    private void Color_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
    {
        // So what ???
    }
}

当有人点击我的矩形时,我只需要能够更改存储在viewModel中存储的列表中的简单布尔值。为什么MVVM如此复杂?

4 个答案:

答案 0 :(得分:21)

在MVVM中,你不应该从后面的代码访问你的视图模型,视图模型和视图彼此都不知道这里的讲座:)

相反,您可以将EventToCommand行为附加到您的控件。这使您可以将控件中的事件绑定到数据上下文中的命令。请在此处查看msdn commands tutorial

如果您迫切希望这样做,您可以访问控件数据上下文属性并将其强制转换为您的视图模型类型,以便访问内部。

var vm = (ViewModelType)this.DataContext;
vm.CommandProperty.Execute(null);

答案 1 :(得分:10)

这并不困难。首先,在Window XAML中创建ViewModel的实例:

查看XAML:

<Window  x:Class="BuildAssistantUI.BuildAssistantWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     xmlns:VM="clr-namespace:MySolutiom.ViewModels">
     <Window.DataContext>
         <VM:MainViewModel />
     </Window.DataContext>
  </Window>

之后,您可以System.Windows.Interactivity.InvokeCommandAction将您的活动翻译成命令:

查看XAML:

<Grid>
 <Rectangle x:Name="Color01" Fill="#FFF4F4F5" HorizontalAlignment="Left" Height="100" Margin="10,29,0,0" Stroke="Black" VerticalAlignment="Top" Width="100" MouseDown="Color_MouseDown">          <interactivity:Interaction.Triggers>
      <interactivity:EventTrigger EventName="MouseDown">
          <interactivity:InvokeCommandAction Command="{Binding MyCommand}"/>
      </interactivity:EventTrigger>
   </interactivity:Interaction.Triggers>
 </Rectangle>
</Grid>

现在,在您的ViewModel中,设置ICommandDelegateCommand实现以绑定到该事件:

<强>视图模型:

public class ViewModel
{
    public ICommand MyCommand { get; set; }

    public ViewModel()
    {
        MyCommand = new DelegateCommand(OnRectangleClicked);
    }

    public void OnRectangleClicked()
    {
        // Change boolean here
    }
}

答案 2 :(得分:6)

快速回答。这也可能有助于其他人

((MyViewModel)(this.DataContext)).MyProperty

答案 3 :(得分:0)

在C#XAML UWP MVVM上下文中。

考虑以下示例

型号:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FrostyTheSnowman.Models
{
    public class User
    {
        public int Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }        

        public override string ToString() => $"{FirstName} {LastName}";

    }
}

ViewModel

using FrostyTheSnowman.Models;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FrostyTheSnowman
{
    public class MainPageViewModel
    {
        public User user { get; set; }

        public MainPageViewModel()
        {
            user = new User
            {
                FirstName = "Frosty",
                LastName = "The Snowman"                
            };
        }
    }
}

查看

<Page
    x:Class="FrostyTheSnowman.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:FrostyTheSnowman"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <Page.DataContext>
        <local:MainPageViewModel x:Name="ViewModel" />
    </Page.DataContext>

    <Grid>
        <StackPanel Name="sp1" DataContext="{Binding user}">

            <TextBox Name="txtFirstName"                     
                 Header="First Name"
                 Text="{Binding FirstName}" />

            <TextBox Name="txtLastName"                     
                 Header="Last Name"
                 Text="{Binding LastName}" />


        </StackPanel>

    </Grid>
</Page>

代码隐藏文件:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409

namespace FrostyTheSnowman
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainPage : Page
    {
        MainPageViewModel vm;

        public MainPage()
        {
            this.InitializeComponent();

            // Initialize the View Model Object
            vm = (MainPageViewModel)this.DataContext;

            System.Diagnostics.Debug.WriteLine(vm.user.ToString() + " was a jolly happy soul");
        }
    }
}

当您运行应用程序时,您会看到:

enter image description here

但更重要的是,调试跟踪将显示:

enter image description here

这表明隐藏的代码确实已经成功访问​​了ViewModel ...

希望这会有所帮助