How can we bind a user-control to a view-model object, when this last contains parameters in his constructor ???
Does the binding using "DataContext" in the view ensure that when we create a view-model, the view is automatically created ??
If you are using an IoC container, this is supported out-of-the-box.
It really depends on the IoC container you are using, but here is an example using Prism Unity container.
The following examples are taken out from the Prism QuickStarts guide
So, at first, we will have to set up the unity container:
public class QuickStartBootstrapper : UnityBootstrapper
{
private readonly CallbackLogger callbackLogger = new CallbackLogger();
/// <summary>
/// Configures the <see cref="IUnityContainer"/>.
///May be overwritten in a derived class to add specific
/// type mappings required by the application.
/// </summary>
protected override void ConfigureContainer()
{
// Here you can do custom registeration of specific types and instances
// For example
this.Container.RegisterInstance<CallbackLogger>(this.callbackLogger);
base.ConfigureContainer();
}
}
Baisically, youre done!
All you have to do now is have your view recieve the viewModel as a parameter in his constructor, like this:
public partial class OverviewView
{
public OverviewView(OverviewViewModel viewModel)
{
InitializeComponent();
this.DataContext = viewModel;
}
}
Unity IoC container will take care of your parameters in the ViewModel even without you having to register those types most of the times.
Please note that in my answer I only refered to the IoC part of the configuration. setting up an entire MVVM application requires a bit more work and varies depending the MVVM framework you are using
I see tons of questions on this topic and the answers are, in my limited C# and WPF experience, overly complex. I cannot believe that Microsoft has made it this difficult (to me ) to implement a collection bound to a Listbox that changes during runtime.
Here's the deal: I have a Listbox that contains items (list of emails, actually). What occurs is that I need the Listbox to refresh when a new email arrives or gets removed from the source Folder. Sounds easy enough, but manipulating the Observable Collection in anyway is causing the dreaded "This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread."
So nevermind for a moment about circumventing this problem by writing dispatcher stuff. Is there some "normal" way to manipulate a collection that's NOT from another thread? -- this is what I'm confused on. Where else would I modify the collection? I'd happily place my code there if this is what's expected.
My current implementation -- which may very well be poor -- is to place the Folder.Items event handlers within the collection class itself that will then add/remove emails from the collection (i.e. itself). This ain't working and I don't really understand how else one would accomplish this.
Okay, I whipped up this code example. This is NOT my application but it pretty much represents how I'm (incorrectly) handling things...and this will throw the 'cannot update source collection thread error'. The example is broken into 3 sections, first is the XAML markup, then Main class and method and the ObservableCollection class.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"
x:Class="WpfApplication1.MainWindow"
x:Name="Window"
Title="MainWindow"
Width="640" Height="480">
<Grid x:Name="LayoutRoot" >
<Border BorderBrush="#FF404020" BorderThickness="5" Margin="0" Background="#FFFFFFC0" CornerRadius="25">
<ListBox x:Name="lbList" Margin="50" FontSize="21.333" DisplayMemberPath="Subject"/>
</Border>
</Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Runtime.InteropServices;
using Microsoft.Office.Interop.Outlook;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MailList ml = new MailList();
public MainWindow()
{
this.InitializeComponent();
Microsoft.Office.Interop.Outlook.Application olApp = Marshal.GetActiveObject("Outlook.Application") as Microsoft.Office.Interop.Outlook.Application;
Folder f = (Folder)olApp.Session.PickFolder(); // User picks MAPI Folder
f.Items.ItemAdd += new ItemsEvents_ItemAddEventHandler(this.UpdateListBox); //Folder.Item add event, calls UpdateListBox
foreach (object o in f.Items)
{
if (o is MailItem)
{
ml.Add((MailItem)o); //Add Mailitems to ml collection
}
}
Binding b = new Binding(); //create binding for ListBox
b.Mode = BindingMode.OneWay;
lbList.DataContext = ml;
lbList.SetBinding(ListBox.ItemsSourceProperty, b);
}
public void UpdateListBox(object o) //Add new MailItem to ml collection
{
if (o is MailItem)
{
ml.Add((MailItem)o);
}
}
}
}
using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using Microsoft.Office.Interop.Outlook;
namespace WpfApplication1
{
public class MailList : ObservableCollection<MailItem>
{
public MailList()
: base()
{
}
}
}
What is supposed to be the problem with dispatching collection changes to the UI-thread? As far as i know that is the usual way to go.
WPF control-derived class has a composition of non-WPF control-derived class. The latter class, say Inner, should trigger an Outer class WPF DependencyProperty change.
Essential invariant is that my Inner class shouldn't force any WPF namespaces to use whereby, Inner is part of API of a dll I am creating. So Inheritance from any WPF class is not appropriate solution.
What could be the best (or at least arbitraty) way to implement a callback from non-.NET derived class to a WPF-Control class to change a DependencyProperty object.
Some hypothetical callback mechanisms found:
c# delegates and c# events.
Can't solve this, becouce it is thrown a runtime exception
The calling thread cannot access this object because a different thread owns it.
when a callback mechanism tries to modify Background property (a DependancyProperty object I think is the key, or at least .NET defined property).
I guess that c# delegates doesn't work in single-threading manner - however, i didn't find this fact while reading c# documentation.
(One solution is through .NET Dispatcher class and Invoke(), but it seems too arbitrary and possibly slow - isn't any more WPF-friendly way?)
I had read about Routed events and DependencyProperties
in WPF documentation (however had't tested this yet), but it seems Routed event cant help (because my Inner class isn't part of a VisualTree) and I should't inherit from DependencyObject.
I read (I suppose) everything relevant to my problem. I'm sorry if some similar kind of question had been asked, I would be glad if you direct me to that thread, if the problem essence is the same.
Simplified example:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows.Media;
using System.Timers;
namespace WpfApplication4
{
internal class Rect:ContentControl
{
Inner inner = new Inner();
public Rect()
{
inner.Rotate += new Inner.RotateEventHandler(rotated);
}
public void rotated(object sender, RotateEventArgs args)
{
Background = Brushes.Blue; //Run time error
VisualTransform = new RotateTransform(args.Angle); //Run time error
}
}
public class Inner
{
Timer timer = new Timer(200);
public Inner()
{
timer.Enabled = true;
timer.Elapsed +=new ElapsedEventHandler(elapsed);
}
public delegate void RotateEventHandler(object sender, RotateEventArgs args);
public event RotateEventHandler Rotate;
public void elapsed(object sender, ElapsedEventArgs e)
{
RotateEventArgs args = new RotateEventArgs();
args.Angle = args.Angle + 45;
OnRotate(args);
}
protected void OnRotate(RotateEventArgs e)
{
if (e != null)
{
Rotate(this, e);
}
}
}
internal class RotateEventArgs
{
private double angle = 0;
public double Angle
{
set { angle = value; }
get { return angle; }
}
}
}
You can make use of DispatchTimer instead of Timer. Have the DispatchTimer in the Rect class itself.
this is my simple try-it application that create a grid with 2 rows. The 1st row's height is bound to a properties. The value I assigned to it only works at run-time. I tried to make it also work when design-time but I failed to do that (I used this thread to write my app).
Please help me to see what I miss. Thank you!
[Edit]
The reason why I do this is that I want to set dynamically the height of the top grid row, ie. Grid.Row="0", to be the title bar height. Somewhere in my app, the view loaded and overlap the title bar.
You're trying to do a very strange trick, which is not supposed to work. Try to make the following changes.
MainWindow.xaml.cs -- try to always keep you code-behind clear.
namespace WpfTryIt
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
}
MainWindow.xaml
<Window x:Class="WpfTryIt.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
xmlns:s ="clr-namespace:WpfTryIt"
>
<Window.DataContext>
<s:FakeDataContext></s:FakeDataContext>
</Window.DataContext>
<Button Content="{Binding Path=BindingHeight}"/>
</Window>
And a new separate data context class, which behave different depending on the mode:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Windows;
namespace WpfTryIt
{
public class FakeDataContext
{
public int BindingHeight
{
get
{
// Check for design mode.
if ((bool)(DesignerProperties.IsInDesignModeProperty.GetMetadata(typeof(DependencyObject)).DefaultValue))
{
//in Design mode
return 100;
}
else
{
return 200;
}
}
}
}
}
I'm trying to implement a WPF application using MVVM (Model-View-ViewModel) pattern and I'd like to have the View part in a separate assembly (an EXE) from the Model and ViewModel parts (a DLL).
The twist here is to keep the Model/ViewModel assembly clear of any WPF dependency. The reason for this is I'd like to reuse it from executables with different (non-WPF) UI techs, for example WinForms or GTK# under Mono.
By default, this can't be done, because ViewModel exposes one or more ICommands. But the ICommand type is defined in the System.Windows.Input namespace, which belongs to the WPF!
So, is there a way to satisfy the WPF binding mechanism without using ICommand?
Thanks!
You should be able to define a single WPF custom routed command in your wpf layer and a single command handler class. All your WPF classes can bind to this one command with appropriate parameters.
The handler class can then translate the command to your own custom command interface that you define yourself in your ViewModel layer and is independent of WPF.
The simplest example would be a wrapper to a void delegate with an Execute method.
All you different GUI layers simply need to translate from their native command types to your custom command types in one location.
WinForms doesn't have the rich data binding and commands infrastructure needed to use a MVVM style view model.
Just like you can't reuse a web application MVC controllers in a client application (at least not without creating mountains of wrappers and adapters that in the end just make it harder to write and debug code without providing any value to the customer) you can't reuse a WPF MVVM in a WinForms application.
I haven't used GTK# on a real project so I have no idea what it can or can't do but I suspect MVVM isn't the optimal approach for GTK# anyway.
Try to move as much of the behavior of the application into the model, have a view model that only exposes data from the model and calls into the model based on commands with no logic in the view model.
Then for WinForms just remove the view model and call the model from the UI directly, or create another intermediate layer that is based on WinForms more limited data binding support.
Repeat for GTK# or write MVC controllers and views to give the model a web front-end.
Don't try to force one technology into a usage pattern that is optimized for another, don't write your own commands infrastructure from scratch (I've done it before, not my most productive choice), use the best tools for each technology.
Sorry Dave but I didn't like your solution very much. Firstly you have to code the plumbing for each command manually in code, then you have to configure the CommandRouter to know about each view/viewmodel association in the application.
I took a different approach.
I have an Mvvm utility assembly (which has no WPF dependencies) and which I use in my viewmodel. In that assembly I declare a custom ICommand interface, and a DelegateCommand class that implements that interface.
namespace CommonUtil.Mvvm
{
using System;
public interface ICommand
{
void Execute(object parameter);
bool CanExecute(object parameter);
event EventHandler CanExecuteChanged;
}
public class DelegateCommand : ICommand
{
public DelegateCommand(Action<object> execute) : this(execute, null)
{
}
public DelegateCommand(Action<object> execute, Func<object, bool> canExecute)
{
_execute = execute;
_canExecute = canExecute;
}
public void Execute(object parameter)
{
_execute(parameter);
}
public bool CanExecute(object parameter)
{
return _canExecute == null || _canExecute(parameter);
}
public event EventHandler CanExecuteChanged;
private readonly Action<object> _execute;
private readonly Func<object, bool> _canExecute;
}
}
I also have a Wpf library assembly (which does reference the System WPF libraries), which I reference from my WPF UI project. In that assembly I declare a CommandWrapper class which has the standard System.Windows.Input.ICommand interface. CommandWrapper is constructed using an instance of my custom ICommand and simply delegates Execute, CanExecute and CanExecuteChanged directly to my custom ICommand type.
namespace WpfUtil
{
using System;
using System.Windows.Input;
public class CommandWrapper : ICommand
{
// Public.
public CommandWrapper(CommonUtil.Mvvm.ICommand source)
{
_source = source;
_source.CanExecuteChanged += OnSource_CanExecuteChanged;
CommandManager.RequerySuggested += OnCommandManager_RequerySuggested;
}
public void Execute(object parameter)
{
_source.Execute(parameter);
}
public bool CanExecute(object parameter)
{
return _source.CanExecute(parameter);
}
public event System.EventHandler CanExecuteChanged = delegate { };
// Implementation.
private void OnSource_CanExecuteChanged(object sender, EventArgs args)
{
CanExecuteChanged(sender, args);
}
private void OnCommandManager_RequerySuggested(object sender, EventArgs args)
{
CanExecuteChanged(sender, args);
}
private readonly CommonUtil.Mvvm.ICommand _source;
}
}
In my Wpf assembly I also create a ValueConverter that when passed an instance of my custom ICommand spits out an instance of the Windows.Input.ICommand compatible CommandWrapper.
namespace WpfUtil
{
using System;
using System.Globalization;
using System.Windows.Data;
public class CommandConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return new CommandWrapper((CommonUtil.Mvvm.ICommand)value);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new System.NotImplementedException();
}
}
}
Now my viewmodels can expose commands as instances of my custom command type without having to have any dependency on WPF, and my UI can bind Windows.Input.ICommand commands to those viewmodels using my ValueConverter like so. (XAML namespace spam ommited).
<Window x:Class="Project1.MainWindow">
<Window.Resources>
<wpf:CommandConverter x:Key="_commandConv"/>
</Window.Resources>
<Grid>
<Button Content="Button1" Command="{Binding CustomCommandOnViewModel,
Converter={StaticResource _commandConv}}"/>
</Grid>
</Window>
Now if I'm really lazy (which I am) and can't be bothered to have to manually apply the CommandConverter every time then in my Wpf assembly I can create my own Binding subclass like this:
namespace WpfUtil
{
using System.Windows.Data;
public class CommandBindingExtension : Binding
{
public CommandBindingExtension(string path) : base(path)
{
Converter = new CommandConverter();
}
}
}
So now I can bind to my custom command type even more simply like so:
<Window x:Class="Project1.MainWindow"
xmlns:wpf="clr-namespace:WpfUtil;assembly=WpfUtil">
<Window.Resources>
<wpf:CommandConverter x:Key="_commandConv"/>
</Window.Resources>
<Grid>
<Button Content="Button1" Command="{wpf:CommandBinding CustomCommandOnViewModel}"/>
</Grid>
</Window>
I needed an example of this so I wrote one using various techniques.
I had a few design goals in mind
1 - keep it simple
2 - absolutely no code-behind in the view (Window class)
3 - demonstrate a dependency of only the System reference in the ViewModel class library.
4 - keep the business logic in the ViewModel and route directly to the appropriate methods without writing a bunch of "stub" methods.
Here's the code...
App.xaml (no StartupUri is the only thing worth noting)
<Application
x:Class="WpfApplicationCleanSeparation.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
</Application>
App.xaml.cs (load up the main view)
using System.Windows;
using WpfApplicationCleanSeparation.ViewModels;
namespace WpfApplicationCleanSeparation
{
public partial class App
{
protected override void OnStartup(StartupEventArgs e)
{
var view = new MainView();
var viewModel = new MainViewModel();
view.InitializeComponent();
view.DataContext = viewModel;
CommandRouter.WireMainView(view, viewModel);
view.Show();
}
}
}
CommandRouter.cs (the magic)
using System.Windows.Input;
using WpfApplicationCleanSeparation.ViewModels;
namespace WpfApplicationCleanSeparation
{
public static class CommandRouter
{
static CommandRouter()
{
IncrementCounter = new RoutedCommand();
DecrementCounter = new RoutedCommand();
}
public static RoutedCommand IncrementCounter { get; private set; }
public static RoutedCommand DecrementCounter { get; private set; }
public static void WireMainView(MainView view, MainViewModel viewModel)
{
if (view == null || viewModel == null) return;
view.CommandBindings.Add(
new CommandBinding(
IncrementCounter,
(λ1, λ2) => viewModel.IncrementCounter(),
(λ1, λ2) =>
{
λ2.CanExecute = true;
λ2.Handled = true;
}));
view.CommandBindings.Add(
new CommandBinding(
DecrementCounter,
(λ1, λ2) => viewModel.DecrementCounter(),
(λ1, λ2) =>
{
λ2.CanExecute = true;
λ2.Handled = true;
}));
}
}
}
MainView.xaml (there is NO code-behind, literally deleted!)
<Window
x:Class="WpfApplicationCleanSeparation.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:WpfApplicationCleanSeparation="clr-namespace:WpfApplicationCleanSeparation"
Title="MainWindow"
Height="100"
Width="100">
<StackPanel>
<TextBlock Text="{Binding Counter}"></TextBlock>
<Button Content="Decrement" Command="WpfApplicationCleanSeparation:CommandRouter.DecrementCounter"></Button>
<Button Content="Increment" Command="WpfApplicationCleanSeparation:CommandRouter.IncrementCounter"></Button>
</StackPanel>
</Window>
MainViewModel.cs (includes the actual Model as well since this example is so simplified, please excuse the derailing of the MVVM pattern.
using System.ComponentModel;
namespace WpfApplicationCleanSeparation.ViewModels
{
public class CounterModel
{
public int Data { get; private set; }
public void IncrementCounter()
{
Data++;
}
public void DecrementCounter()
{
Data--;
}
}
public class MainViewModel : INotifyPropertyChanged
{
private CounterModel Model { get; set; }
public event PropertyChangedEventHandler PropertyChanged = delegate { };
public MainViewModel()
{
Model = new CounterModel();
}
public int Counter
{
get { return Model.Data; }
}
public void IncrementCounter()
{
Model.IncrementCounter();
PropertyChanged(this, new PropertyChangedEventArgs("Counter"));
}
public void DecrementCounter()
{
Model.DecrementCounter();
PropertyChanged(this, new PropertyChangedEventArgs("Counter"));
}
}
}
Just a quick and dirty and I hope it's useful to someone. I saw a few different approaches through various Google's but nothing was quite as simple and easy to implement with the least amount of code possible that I wanted. If there's a way to simplify even further please let me know, thanks.
Happy Coding :)
EDIT: To simplify my own code, you might find this useful for making the Adds into one-liners.
private static void Wire(this UIElement element, RoutedCommand command, Action action)
{
element.CommandBindings.Add(new CommandBinding(command, (sender, e) => action(), (sender, e) => { e.CanExecute = true; }));
}
Instead of the VM exposing commands, just expose methods. Then use attached behaviors to bind events to the methods, or if you need a command, use an ICommand that can delegate to these methods and create the command through attached behaviors.
Off course this is possible. You can create just another level of abstraction.
Add you own IMyCommand interface similar or same as ICommand and use that.
Take a look at my current MVVM solution that solves most of the issues you mentioned yet its completely abstracted from platform specific things and can be reused. Also i used no code-behind only binding with DelegateCommands that implement ICommand. Dialog is basically a View - a separate control that has its own ViewModel and it is shown from the ViewModel of the main screen but triggered from the UI via DelagateCommand binding.
See full Silverlight 4 solution here Modal dialogs with MVVM and Silverlight 4
I think you are separating your Project at wrong point. I think you should share your model and business logic classes only.
VM is an adaptation of model to suit WPF Views. I would keep VM simple and do just that.
I can't imagine forcing MVVM upon Winforms. OTOH having just model & bussiness logic, you can inject those directly into a Form if needed.
" you can't reuse a WPF MVVM in a WinForms application"
For this please see url http://waf.codeplex.com/ , i have used MVVM in Win Form, now whenver i would like to upgrade application's presentation from Win Form to WPF, it will be changed with no change in application logic,
But i have one issue with reusing ViewModel in Asp.net MVC, so i can make same Desktop win application in Web without or less change in Application logic..
Thanks...