开发者

WPF+MVVM: How to display VM via resource dictionary

开发者 https://www.devze.com 2023-01-07 05:36 出处:网络
At the moment I am creating new instance of both View and ViewModel and assign view.DataContext = vm in the application in the handler of \'Startup\' application event

At the moment I am creating new instance of both View and ViewModel and assign view.DataContext = vm in the application in the handler of 'Startup' application event

In the http://msdn.microsoft.com/en-us/magazine/dd419663.aspx in the "Applyi开发者_如何学Cng a View to a ViewModel" chapter I've read that it would be a good idea to bind ViewModel object to view via resources.

Am I correctly understand that using suggested approach I should:

  1. Create a resource in the "MainPage" that will have a "DataTemplate" section for each pair of View/ViewModel;
  2. Bind instance of the ViewModel object to the MainPage?

Am I right?

P.S. Actually, I've tried to do that but got few issues and want to know if I am going by the proper way. If no, please point me how that should be done in the right way.


How this technique works is that instead of finding and creating views directly let wpf find the view through data templates. so when you have the following in your application resources. This drives the UI based on what ViewModel you want to display and don't have to worry about coding up the view.

<DataTemplate DataType="{x:Type vm:MyViewModel}">
    <ui:MyView />
</DataTemplate>

Note: vm: and ui: are just xml namespaces declared in the top element of the resource file. you can then just create a generic window that will 'find' the view via a ContentControl

<Window ...>
    <ContentControl Content="{Binding}" />
</Window>

var window = new Window();
window.DataContext = new MyViewModel();
window.Show();

This will display the window embedding MyView as the content of the window. Provided you have your bindings set in your view pointing to properties in your viewmodel the wire up succeed. No need to 'new' up a view. The main window can be reused simply by reassigning a different view model to the data context.

Also if you let us know what specific issues you are having we will be able to provide a more specific answer if the above is not what you are looking for.

HTH


I used to do a key/value pair for all of my ViewModel/View like aqwert suggests, but once you get a couple dozen,or more than one :), ViewModels it starts getting pretty tedious and prone to typos.

I personally like an IValueConverter doing the work for me and using Convention for the location of the View.

For example let's say I have my view models in namespace MyApp.ViewModels and all of my Views in namespace MyApp.Views and I have a suffix of ViewModel behind all of my VMs and a suffix of View behind all of my Views

All I have to do is:

1) Have all of my ViewModels inherit from a base class ViewModelBase

2) Put this in my application resource dictionary

<m:ViewModelConverter x:Key="ViewModelConverter"/>
<DataTemplate DataType="{x:Type vm:ViewModelBase}">
    <ContentControl Content="{Binding Converter={StaticResource ViewModelConverter}}"/>
</DataTemplate>

3) Create my converter, the following is just an example, you can modify to meet your convention.

public class ViewModelConverter : IValueConverter
{
    #region IValueConverter Members

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value != null)
        {
            Type ViewModelType = value.GetType();
            string ViewNameSpace = ViewModelType.Namespace.Replace("ViewModel", "View");
            string ClassName = ViewModelType.Name.Replace("Model", string.Empty);
            Type ViewType = Type.GetType(string.Format("{0}.{1}", ViewNameSpace, ClassName));
            if (ViewType != null)
                return Activator.CreateInstance(ViewType);
        }
        return value;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotSupportedException();
    }

    #endregion
}

The above will try and find the view, if it doesn't it will just return the ViewModel that it was trying to convert (which WPF will just call .ToString() on)

You don't have to worry about actual wiring of ViewModel to the View's DataContext because WPF does that automatically.

And then I'm done. I don't have to touch my resource file any more. :)

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号