How do I make the simplest viewmodel work?

2019-12-16 19:17发布

Im trying to understand how to use a viewmodel to bind data to a wpf window but cannot find any simple examples or explanations on how that is achieved.

This is what I have so far:

ViewModel.cs

public class ViewModel
{
    public string Info = "Infoo";
}

MainWindow.xaml.cs

public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new ViewModel();
        }
    }

MainWindow.xaml

<Window x:Class="PeopleApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:PeopleApp"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <TextBox x:Name="textBox" HorizontalAlignment="Left" Height="23" Margin="212,137,0,0" TextWrapping="Wrap" Text="{Binding Info}" VerticalAlignment="Top" Width="120"/>

    </Grid>
</Window>

Why does the textbox not show "Infoo"? What am I missing?

Edit:

I've changed the field in the ViewModel to a property, but how do I connect the ViewModel to actual data?

标签: c# wpf mvvm
2条回答
相关推荐>>
2楼-- · 2019-12-16 20:03

Your View(Window) and ViewModel(class) are various parts of application. You should use DataContext property to interact between View and ViewModel and create properties, not fields like you've done in your case. For example:

View:

<Grid>        
    <TextBlock Text="{Binding DisplayTime}" />        
</Grid>

ViewModel:

public class MyViewModel
{
    private string displayTime=DateTime.Now.ToString;
    public string DisplayTime
    {
        get { return displayTime; }
        set { displayTime = value; }
    }
}

There are many approaches to set DataContext:

The first approach. In view:

<Window.DataContext>
   <local:MainWindowViewModel/>
</Window.DataContext>

The second approach. You should override OnStartUp() method of App.xaml.cs

public partial class App : Application
{
     protected override void OnStartup(StartupEventArgs e)
    {
            base.OnStartup(e);
            MainWindow app = new MainWindow();
            ProductViewModel context = new ProductViewModel();
            app.DataContext = context;
            app.Show();
     }
}

The third approach. In constructor of Windows:

public partial class MainWindow : Window
{
     public MainWindow()
     {
          InitializeComponent();
          DataContext=new MainWindowViewModel();
     }
}

The fourth approach. You can set DataContext through DependencyInjection by UnityContainer. But DependencyInjection, Prism and UnityContainer are other questions and goes from this scope of the question. Just for example:

protected override void RegisterTypes()
{ 
    unityContainer.RegisterType<object, ItemControl>("ModuleAUpper");
    unityContainer.RegisterType<IViewModelItemControl, ViewModelItemControl>();
    unityContainer.RegisterTypeForNavigation<ItemControl>();
}
查看更多
爷的心禁止访问
3楼-- · 2019-12-16 20:21

Mistakes in your code:

  • You need to have property on the VM not the public field.
  • you need to set the value for the property of VM instance before assigning it to the DataContext of MainWindow

This should work.

MainWindow.xaml

<Window x:Class="PeopleApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:PeopleApp"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>       
            <TextBox x:Name="textBox" HorizontalAlignment="Left" Height="23" Margin="212,137,0,0" TextWrapping="Wrap" Text="{Binding Info}" VerticalAlignment="Top" Width="120"/>        
    </Grid>
</Window>

MainWindow.xaml.cs

public partial class MainWindow : Window
{
    public MainWindow()
    {         
        InitializeComponent();
        this.DataContext = new ViewModel() { Info = "Infoo" };
    }    
}

ViewModel.cs

public class ViewModel
{
    public string Info { get; set; }        
}
查看更多
登录 后发表回答