How do I databind to a Winform control that is hosted in a WPF control? - wpf

I just thought about converting one of our custom controls to WPF, however it uses another custom control of ours that is written Winforms.
As there is little point in using WPF without MVVM. How can I databind to a Winforms control that is used within a WPF control.
(I don’t have much WPF experience, so I may be missing the point completely)

I think you will have to wrap the WinForms control in a class exposing DependencyProperties or at least implementing INotifyPropertyChanged.
So you'd have a class such as:
public class WinFormsWrapper : WindowsFormsHost
{
//You'll have to setup the control as needed
private static MyWinFormsControl _control;
public static readonly DependencyProperty IsSpinningProperty = DependencyProperty.Register("IsSpinning", typeof(bool), typeof(WinFormsWrapper),
new FrameworkPropertyMetadata(_control.IsSpinning, new PropertyChangedCallback(IsSpinning_Changed)));
private static void IsSpinning_Changed(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
_control.IsSpinning = (bool)e.NewValue;
}
public bool IsSpinning
{
get { return (bool)GetValue(IsSpinningProperty); }
set { SetValue(IsSpinningProperty, value); }
}
}
Assuming that you have an IsSpinning property on your WinForms control. Depending on your needs, it may be simpler to implement INotifyPropertyChanged instead of using DependencyProperties.
Added by Ian Ringrose:
This example code is clearly wrong (see comments about _control being static), but shows how to solve the problem. As I am not using WPF at present, I am not going to edit the code as I can't test my edits.
I am keeping this answer as the accepted answer, as it contains the information needed to solve the problem.
I have added this to the answer, as comments do sometimes get deleted and this is getter views from people doing google searches.

Related

How to write a WPF user control in F#?

Can a WPF user control be written in F#?
Lets say I have a standard WPF/C# user control as:
public class DataGridAnnotationControl : UserControl
{
static DataGridAnnotationControl()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(DataGridAnnotationControl), new FrameworkPropertyMetadata(typeof(DataGridAnnotationControl)));
}
public DataGridAnnotationControl()
{
BorderBrush = Brushes.Black;
Background = Brushes.AliceBlue;
BorderThickness = new Thickness(20, 20, 20, 20);
}
public string LastName
{
get { return (string)GetValue(LastNameProperty); }
set { SetValue(LastNameProperty, value); }
}
public static readonly DependencyProperty LastNameProperty =
DependencyProperty.Register("LastName", typeof(string), typeof(DataGridAnnotationControl), new PropertyMetadata(string.Empty));
}
How is this coded in F#?
TIA
In general, creating the user control in F# (without a library) will typically be quite different than in C#.
The main issue is you can't use partial classes, so the designer will not function. Even if you ditch the designer, the typical workflow with XAML files does not work properly. To do this in "pure" F#, you typically need to write the UI in code vs doing it in XAML and allowing the generated InitializeComponent() method to wire things together.
However, one way to get there in a more "natural" method is to use FsXaml. It allows you to write user controls directly which become usable in a similar way to C# developed ones. This is done via a type provider and overriding the default information.

WPF best practice to get current MainWindow instance?

I got a warning that this may be a subjective question and might be closed, but I'm going to ask anyway.
I'm basically trying to access a button on my MainWindow in a WPF application from a UserControl that gets loaded up from within the MainWindow.
I'm currently accessing it like this from the UserControl's code behind:
((MainWindow)Application.Current.MainWindow).btnNext
But it does look messy, and from what I've read is not considered a best practice. Anyone able to provide an answer that constitutes a best practice for Accessing controls / properties from the current instance of a MainWindow - or any other active windows / views for that matter?
You can get a reference to the parent window of the UserControl using the Window.GetWindow method. Call this once the UserControl has been loaded:
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
this.Loaded += (s, e) =>
{
MainWindow parentWindow = Window.GetWindow(this) as MainWindow;
if (parentWindow != null)
{
//...
}
};
}
}
You could also access all open windows using the Application.Current.Windows property:
MainWindow mainWindow = Application.Current.Windows.OfType<MainWindow>().FirstOrDefault();
Which one to use depends on your requirements. If you want a reference to the application's main window for some reason, you could stick with your current approach. If you want a reference to the parent window of the UserControl, using the Window.GetWindow method would be better.
The best practice is generally to use the MVVM design pattern and bind UI controls to source properties of a view model that may be shared by several views. But that's another story. You could refer to the following link for more information about the MVVM pattern: https://msdn.microsoft.com/en-us/library/hh848246.aspx

Using WPF, MVVM and Bindings with a WinForm UserControl, how to integrate successfully?

I have a WinForm UserControl inside a WPF window and the WPF code is using the MVVM pattern.
What is the best way to successfully integrate the WinForm control into the MVVM pattern?
Can I use some form of binding from the WPF side?
Let's say that I want to handle some events from the WF control, is there a way to fully go MVVM?
Thanks.
Note that this doesn't really answer the questions (I should have read better). If you're interested in using a WPF control in a WinForms app, here's an approach. My scenario is:
1) Have a WinForms control that is used many places in my app.
2) Want to develop a WPF implementation that will use the MVVM pattern.
3) Want to write the control as a proper WPF control complete with dependency properties so it can be used properly when my app is eventually all WPF.
4) Want to keep the same WinForms control and API to not break existing client code in my app.
Most everything was straightforward except for having my WinForms control raise events when properties of my WPF control changed. I wanted to use a binding but since the source of a binding must be a DependencyObject and a System.Windows.Forms.UserControl is not, I had to make a simple nested class. I wrote my WPF control exactly as if I was integrating it into a WPF application, and just did some extra thunking to get my WinForms wrapper to work.
Here's code for my WPF control:
public partial class MonkeySelector : UserControl
{
public static readonly DependencyProperty SelectedMonkeyProperty =
DependencyProperty.Register(
"SelectedMonkey", typeof(IMonkey),
typeof(MonkeySelector));
public MonkeySelector()
{
InitializeComponent();
}
protected override void OnInitialized(EventArgs e)
{
base.OnInitialized(e);
// Note: No code is shown for binding the SelectedMonkey dependency property
// with the ViewModel's SelectedMonkey property. This is done by creating
// a Binding object with a source of ViewModel (Path = SelectedMonkey) and
// target of the SelectedMonkey dependency property. In my case, my
// ViewModel was a resource declared in XAML and accessed using the
// FindResource method.
}
public IMonkey SelectedMonkey
{
get { return (IMonkey)GetValue(SelectedMonkeyProperty); }
set { SetValue(SelectedMonkeyProperty, value); }
}
}
Here's the code for my WinForms control:
public partial class WinFormsMonkeySelector : UserControl
{
public event EventHandler SelectedMonkeyChanged;
private MonkeySelector _monkeySelector;
private WpfThunker _thunker;
public WinFormsMonkeySelector()
{
InitializeComponent();
_monkeySelector = new MonkeySelector();
_elementHost.Child = _monkeySelector;
System.Windows.Data.Binding binding = new System.Windows.Data.Binding("SelectedMonkey");
binding.Source = _monkeySelector;
binding.Mode = System.Windows.Data.BindingMode.OneWay;
_thunker = new WpfThunker(this);
// Note: The second parameter here is arbitray since we do not actually
// use it in the thunker. It cannot be null though. We could declare
// a DP in the thunker and bind to that, but that isn't buying us anything.
System.Windows.Data.BindingOperations.SetBinding(
_thunker,
MonkeySelector.SelectedMonkeyProperty,
binding);
}
protected virtual void OnSelectedMonkeyChanged()
{
if (SelectedMonkeyChanged != null)
SelectedMonkeyChanged(this, EventArgs.Empty);
}
public IMonkey SelectedMonkey
{
get { return _monkeySelector.SelectedMonkey; }
set { _monkeySelector.SelectedMonkey = value; }
}
private class WpfThunker : System.Windows.DependencyObject
{
private WinFormsMonkeySelector _parent;
public WpfThunker(WinFormsMonkeySelector parent)
{
_parent = parent;
}
protected override void OnPropertyChanged(System.Windows.DependencyPropertyChangedEventArgs e)
{
base.OnPropertyChanged(e);
// Only need to check the property here if we are binding to multiple
// properties.
if (e.Property == MonkeySelector.SelectedMonkeyProperty)
_parent.OnSelectedMonkeyChanged();
}
}
}
Personally, I would handle this by creating a WPF UserControl that wraps the Windows Forms control. This would allow you to encapsulate all of the required code-behind into your WPF Control, and then use it in a pure MVVM manner.
It will be difficult to stay "pure" MVVM using a Windows Forms control directly, as Windows Forms controls typically require a different binding model, as well as typically requiring direct event handling.
You might have a look at the WAF Windows Forms Adapter. It shows a possible way to use Windows Forms together with MVVM.

When to use a WPF Dependency Property versus INotifyPropertyChanged

Do folks have any guidance on when a simple .NET property that fires INotifyPropertyChanged.PropertyChanged is sufficient in a view model? Then when do you want to move up to a full blown dependency property? Or are the DPs intended primarily for views?
There are a few approaches:
1. The dependency property
While you using the dependency property it makes the most sense in elements-classes that have a visual appearance (UIElements).
Pros:
WPF do the logic stuff for you
Some mechanism like animation use only dependency property
'Fits' ViewModel style
Cons:
You need to derive form DependencyObject
A bit awkward for simple stuff
Sample:
public static class StoryBoardHelper
{
public static DependencyObject GetTarget(Timeline timeline)
{
if (timeline == null)
throw new ArgumentNullException("timeline");
return timeline.GetValue(TargetProperty) as DependencyObject;
}
public static void SetTarget(Timeline timeline, DependencyObject value)
{
if (timeline == null)
throw new ArgumentNullException("timeline");
timeline.SetValue(TargetProperty, value);
}
public static readonly DependencyProperty TargetProperty =
DependencyProperty.RegisterAttached(
"Target",
typeof(DependencyObject),
typeof(Timeline),
new PropertyMetadata(null, OnTargetPropertyChanged));
private static void OnTargetPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Storyboard.SetTarget(d as Timeline, e.NewValue as DependencyObject);
}
}
2. The System.ComponentModel.INotifyPropertyChanged
Usually, when creating a data object, you’ll use this approach. It is simple and neat solution for Data-like stuff.
Pros and Cons - complementary to 1. You need to to implement only one event (PropertyChanged).
Sample:
public class Student : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (PropertyChanged != null)
PropertyChanged(this, e);
}
}
private string name;
public string Name;
{
get { return name; }
set {
name = value;
OnPropertyChanged(new PropertyChangedEventArgs("Name"));
}
}
3.PropertyNameChanged
Rising an event for each property with specified name(f.e. NameChanged). Event must have this name and it is up to you to handle/rise them. Similar approach as 2.
4. Get the binding
Using the FrameworkElement.GetBindingExpression() you can get the BindingExpression object
and call BindingExpression.UpdateTarget() to refresh.
First and second are the most likely depending what is your goal.
All in all, it is Visual vs Data.
As far as I know, DependencyProperty is only required when you need
PropertyValue inheritence
you need to allow the property to be set in Style setters
Use animation for the property
etc.
These features will not be available with normal properties.
DependencyProperty is required if you want to allow a binding to be set on the property. Usually this is for custom UIElements you create. You want to allow people to be able to bind data to your UIElements.
<local:MyUIElement MyProperty={Binding Path=SomethingToBindTo} />
To do this requires that MyProperty is a dependancy property
The main problem I see with INotifyPropertyChanged is if you viewmodel is complex containing many nested types it appears that you have to bubble the PropertyChanged event up through the hierarchy.
As the other answers have already said enough about when to create dependency property. i.e.
PropertyValue inheritence
you need to use binding on a property
Use animation for the property
The one more perspective/question on this is "In a WPF application is makes sense to create dependency properties in a control cause they are likely to change during user interaction like Height,width, text,content, background etc but what about other classes like Behaviors Classes(Non UI classes). Do properties in those classes need to be a dependency property?"
I won't say for very absolute or emphasis on some set of rules here but you should create your properties as DP. As from design perspective if a property is DP it's always in default form of WPF to use/bind.i.e.
As a DP is much more fast/natural in reflecting changes compare to a normal CLR property.
A DP has validation mechanism to validate the value assigned and a default structure to revert the value.
A DP has Coerce value callback to control the limits of property.
A DP has meta data associated with it unlike CLR property.
In terms of practices I've seen people doing many mistakes in nested bindings and then raising changes these kind of faults doesn't happen with a DP cause of it's design and compatibility of raising change itself. So with a little extra syntax you put a flexibility/performance/ easeness to your application. So go for it wherever affordable.
Still can't say sure for ViewModel classes/other helper classes. will update the answer if found convincing reasons in future.
Just a post worth reading on this topic

MVVM Focus To Textbox

How would I set focus to a TextBox without specifying the name for that TextBox? At the moment I am doing the following
<Window FocusManager.FocusedElement="{Binding ElementName=Username}">
<Grid>
<TextBox Text="{Binding Username}" Name="Username" />
</Grid>
</Window>
Is there any way of doing this without specifying a Name for the TextBox. As I believe in MVVM having a Name element usually means bad design?
As I believe in MVVM having a Name element usually means bad design?
No, it’s not.
The MVVM pattern is not about eliminating all the code from code-behind files.
It is about separating of concerns and increasing the testability.
View related code like focus handling should remain in the code-behind file of the View. But it would be bad to see application logic or database connection management in the code-behind file of the View.
MVVM examples with code in the code-behind files without violating the MVVM pattern can be found at the WPF Application Framework (WAF) project.
The simple way is to set focus in UserControl_Load event
this.txtBox.Focus();
txtBox.Focusable = true;
Keyboard.Focus(txtBox);
MVVM doesn't mean you can not put code in the code behind file.
In fact, Do not let any pattern restrict you to find the best way of coding.
I have documented a "pure MVVM" way to do this in my answer to a similar problem. The solution involves using Attached Properties and a framework for passing interface commands from the ViewModel back to the View.
Code behind should be avoided when possible, even more when it is in the view. I had the same problem and for simple purposes the best answer is this one as it only modifies the view:
WPF MVVM Default Focus on Textbox and selectAll
If you are looking to set again focus as you interact with other UserControl elements, this will do the trick:
Set focus on textbox in WPF from view model (C#)
I lost 3 days figuring this out, I hope this can help.
As I believe in MVVM having a Name element usually means bad design?
No, it’s not.
According to Microsoft MVP's not only is naming controls is WPF bad practice, it is a quite substantial hit on performance. Just wanted to pass along some words of wisdom
I agree with Sean Du about not letting any pattern totally restrict you, I think performance hit should be avoided whenever possible.
Actually, I found the boolean attached property solution a bit dirty and clumsy in the way that you have to find a twist in order to be sure that the next set of your view model property will really raise the attached property changed event.
A simple and more elegant solution is to bind your behavior on property type for which you can be sure that the next value will always be different from the previous one and thus be sure that your attached property changed event will raise every times.
The most simple type that comes into mind is the int. The solution is then the usual combination of :
The behavior:
public static class TextBoxFocusBehavior
{
public static int GetKeepFocus(DependencyObject obj)
{
return (int)obj.GetValue(KeepFocusProperty);
}
public static void SetKeepFocus(DependencyObject obj, int value)
{
obj.SetValue(KeepFocusProperty, value);
}
// Using a DependencyProperty as the backing store for KeepFocus. This enables animation, styling, binding, etc...
public static readonly DependencyProperty KeepFocusProperty =
DependencyProperty.RegisterAttached("KeepFocus", typeof(int), typeof(TextBoxFocusBehavior), new UIPropertyMetadata(0, OnKeepFocusChanged));
private static void OnKeepFocusChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
TextBox t = d as TextBox;
if (t != null)
{
t.Focus();
}
}
}
The view model property:
public int InputFocus
{
get { return _inputFocus; }
private set
{
_inputFocus = value;
Notify(Npcea.InputFocus);
}
}
The use of the attached behavior:
<TextBox v:TextBoxFocusBehavior.KeepFocus="{Binding InputFocus}"/>
And finaly the use of the property in the VM:
public void YouMethod()
{
//some code logic
InputFocus++;//<= the textbox focus
}
Some REALLY bad minded spirits might say that this logic is bound to the int32 size limitation. Well... I will just choose to ignore them right now ;-)

Resources