简体   繁体   English

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

[英]How can I access my ViewModel from code behind

I don't understand how I can create a command to create a MVVM clickable rectangle.我不明白如何创建命令来创建 MVVM 可点击矩形。 Here is my code:这是我的代码:

<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"/>

On my first rectangle you can see I created a code behind event.在我的第一个矩形上,您可以看到我在事件背后创建了一个代码。 First I don't know how to access my ViewModel from the code behind.首先,我不知道如何从后面的代码访问我的 ViewModel。 Two it's not really MVVM.二它不是真正的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 ???
    }
}

I just need to be able to change a simple boolean value stored in a list stored in my viewModel when someone click on my rectangle.当有人单击我的矩形时,我只需要能够更改存储在我的 viewModel 中存储的列表中的简单布尔值。 Why it is so complicate to do with MVVM?为什么与 MVVM 相关如此复杂?

In MVVM you shouldn't be accessing your view model from code behind, the view model and view are ignorant of each other a here endeth the lecture :)在 MVVM 中,您不应该从后面的代码访问您的视图模型,视图模型和视图彼此不了解,讲座到此结束:)

Instead you can attach the EventToCommand behaviour to your control.相反,您可以将 EventToCommand 行为附加到您的控件。 This lets you bind an event in the control to a command in the data context.这使您可以将控件中的事件绑定到数据上下文中的命令。 See msdn commands tutorial here.请参阅此处的msdn 命令教程

If you are desperate to do it, you can access the controls data context property and cast it to your view model type to give access to the internals.如果您不顾一切地这样做,您可以访问控件数据上下文属性并将其转换为您的视图模型类型以访问内部结构。

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

Quick answer.快速回答。 This might help others as well这也可能对其他人有帮助

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

This isn't too difficult.这不是太难。 First, create an instance of your ViewModel inside your Window XAML:首先,在 Window XAML 中创建一个 ViewModel 实例:

View XAML:查看 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>

After that, you can System.Windows.Interactivity.InvokeCommandAction to translate your event to a command:之后,您可以System.Windows.Interactivity.InvokeCommandAction将您的事件转换为命令:

View XAML:查看 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>

Now, in your ViewModel, set up an ICommand and the DelegateCommand implementation to bind to that event:现在,在您的 ViewModel 中,设置ICommandDelegateCommand实现以绑定到该事件:

ViewModel:视图模型:

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

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

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

In a C# XAML UWP MVVM Context.在 C# XAML UWP MVVM 上下文中。

Consider the following example考虑下面的例子

Model:模型:

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"                
            };
        }
    }
}

View看法

<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>

code-behind file:代码隐藏文件:

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");
        }
    }
}

When u run the app you'll see:当你运行应用程序时,你会看到:

在此处输入图片说明

But more importantly, the debug trace will show:但更重要的是,调试跟踪将显示:

在此处输入图片说明

It shows that the code-behind has indeed successfully accessed the ViewModel...它表明代码隐藏确实成功访问了ViewModel...

Hope this helps希望这可以帮助

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM