Force binding in WPF - wpf

I'm writing tests which will check correctness of Binding elements specified in XAML. They work so far, the only issue is that I do not know how to correctly force databinding to happen. Surprisingly it is not enough to simply set something in DataContext, binding won't happen until you show your control/window. Please not that I'm writing 'unit'-tests and I'd like to avoid showing any windows.
Take a look at following code:
// This is main class in console application where I have all WPF references added
public class Program
{
[STAThread]
public static void Main()
{
var view = new Window();
BindingOperations.SetBinding(view, Window.TitleProperty, new Binding("Length"));
view.DataContext = new int[5];
//view.Show(); view.Close(); // <-- this is the code I'm trying not to write
Console.WriteLine(view.Title);
}
}
Here I'm creating a Window and putting an array as DataContext to that window. I'm binding Window.Title to Array.Length so I expect to see number 5 printed in console. But until I Show window (commented line) I will get empty string. If I uncomment that line then I will receive desired 5 in console output.
Is there any way I can make binding happen without showing a window? It is pretty annoying to look at ~20 windows while launching tests.
P.S.: I know I can make windows more transparent and etc, but I'm looking for more elegant solution.
UPDATE Code above is simplified version of what I really have. In real code I receive a View (some UIElement with bindings) and object ViewModel. I do not know which exactly binding there were set on View, but I still want all of them to be initialized.
UPDATE 2: Answering to the questions regarding what I test and I why. I do not intend to test that classes like Binding, BindingBase, etc are working as expected, I assume they are working. I'm trying to test that in all my XAML files I have written bindings correctly. Because bindings are stringly typed things, they are not verified during compilation and by default they cause only errors in output window, which I'm missing occasionally. So if we take my example from above and if we will made a typo there in binding: {Binding Lengthhh} then my tests will notify you that there is no property with name Lengthhh available for binding. So I have around 100 XAML files and for each XAML I have a test (3-5 lines of code) and after launching my tests I know for sure that there are no binding errors in my solution.

The bindings are updated by the dispatcher with the DispatcherPriority.DataBind - so if you wait for a dummy task with SystemIdle priority you are sure that any pending databinding is done.
try
{
this.Dispatcher.Invoke(DispatcherPriority.SystemIdle, new Action(() => { }));
}
catch
{
// Cannot perfom this while Dispatcher in suspended mode
}

If you are trying to test correctness of your view, I suggest you test your view :-)
Why not run the UI from a unit test and write code that checks content of UI after changing data.
VS2010 does have GUI testing, or you could take a look at the code of tools such as Snoop.
Edit following comment:
If ALL you want to do is test a few simple bindings, try writing a static code test that runs as a post build event using reflection on view models and regular expressions on XAMLs. Add attributes on VM or use a config file so your test will know which view receives which View Model as DataContext. Compare property names and types in View Models with binding strings in View (automatically search XAML for these) and throw exception (thus failing build) if strings do not match.
If your bindings are more complex (converters, multibindings, ...) this may be a bit more complicated to implement.

I think you should first set the DataContext and then do the Binding, e.g.:
view.DataContext = new int[5];
BindingOperations.SetBinding(view, Window.TitleProperty, new Binding("Length"));
I'm not sure if this is real solution for your general problem, but it works in this case.

I don't believe the Window's bindings will run without calling Show or ShowDialog, because that is the only way it gets associated with the UI message loop/dispatcher.
Your best bet would be to set it to be as least visible as possible, potentially using an extension method to clean things up:
public static void PokeWindowDispatcher(this Window window)
{
window.WindowState = WindowState.Minimized;
window.ShowInTaskbar = false;
window.Visibility = Visibility.None;
using (var wait = new ManualResetEvent())
{
Action<object, RoutedEventArgs> loaded = (sender, e) => wait.Set();
window.Loaded += loaded;
try
{
window.Show();
wait.WaitOne();
}
finally
{
window.Loaded -= loaded;
window.Close();
}
}
}

I had the same problem, and from sixlettervariables gave me an idea. It's very simple.
I am using WPF in WinForms application, so I use ElementHost control to host Wpf controls on WinForms control. To enforce WinForms control initialization you can just read value of Handle (which is actually Windows HWND) and this will force control to fully initialize itself including child ElementHost and all Wpf binding work.
I didn`t try to perform the same thing for pure Wpf control. But you can easily use ElementHost to initialize your Wpf controls like this:
var el = new ElementHost();
var p = new TextBlock();
p.DataContext = new { Data = "1234" };
p.SetBinding(TextBlock.TextProperty, "Data");
el.Child = p;
var t = el.Handle;
Debug.Assert(p.Text == "1234");
PS: Found, that everything work better, if you first set DataContext and only then force a Handle to be created (just like my example). But, I think, this is already the case for you, so should not be a problem.

Have you tryed to use the IsDataBound
http://msdn.microsoft.com/en-us/library/system.windows.data.bindingoperations.isdatabound.aspx
Also check this out:
System.Windows.Interop.WindowInteropHelper helper = new System.Windows.Interop.WindowInteropHelper(view).EnsureHandle();
http://msdn.microsoft.com/en-us/library/system.windows.interop.windowinterophelper.ensurehandle.aspx
My other question is why you trying to do a UNIT test on something that has been technically tested already? By the way I am not critising, just want to understand a little better.

Not sure, but maybe something like this will work?
view.GetBindingExpression(Window.TitleProperty).UpdateTarget();

Related

In a constructor for a WPF Window, what should go before InitializeComponent() and what after?

In general, I've been initializing the properties of the Window itself before InitializeComponent() and setting up controls contained within afterwards. However, I haven't been all that consistent, and I haven't really noticed a problem with the ordering. So:
Am I (potentially) doing something horrible? In particular, are there any issues with setting properties of child controls before InitializeComponent()?
What is good style in this regard?
Edit: Since the first two answers I got were a little bit contradictory, let me be more specific:
public Foo Foo {get; protected set}
public FooWindow (Foo foo)
{
Foo = foo;
this.Closing += FooWindow_Closing;
Foo.Frobbed += Foo_Frobbed;
InitializeComponent();
this.DataContext = this;
this.Title = Foo.Name() + " Window";
FooListView.ItemSource = Foo.CalculateList();
FocusManager.SetFocusedElement(this, FooListView);
}
Is this about right? Should I just be doing MVVM and not have anything in my Window constructor?
By calling InitializeComponents after some other code you run the risk of accidentally overwriting properties with things that were set in the XAML or of using an uninitialized object. Usually the code-behind is a higher priority than the XAML so I would leave InitializeComponents (aka, parse and load the XAML) at the top.
In answer to your specific questions:
Am I (potentially) doing something horrible? In particular, are there any issues with setting properties of child controls before InitializeComponent()?
Chances are that your child controls aren't available to you in code yet until you've called InitializeComponents. It would generally be bad form to do this.
What is good style in this regard?
This is going to be a matter of taste, but generally I would recommend that if you're going to take advantage of the separation that XAML affords you then I would take it as far as you can. If you're doing things that are logically about the UI try to do it in XAML. This isn't so much an MVVM thing as it is a separation of presentation from logic. Most of what you have in your sample code can be done declaratively, even if just through ValueConverters.
E.g if Foo was a DependencyProperty then you could also attach it in XAML and add the callbacks as part of the ValueChanged callback. Again, this isn't MVVM, but it is pretty fundamental to WPF.
For most other things, you actually probably want to wait until OnLoaded is called, rather than doing the work in the constructor.
Hope that helps,
I usually call anything that does not require the Visual Tree before I call InitializeComponent().
All of my implementations use the MVVM pattern, so I prefer to have my ViewModel instantiated and populated before the UI is loaded to the client.
If you always load InitializeComponent() first, you run the risk of creating a bad user experience by showing an unpopulated view that suddenly updates versus one that is populated when it comes into view.

WPF memory allocation leaps using binding, inotifypropertychanged and dependency property

I'm writing a program that uses a bunch of two-way bindings and the amount of memory used has become a huge problem. In my full application, I start at 50Mb, and then, just by using the bindings (i.e. changing the value on one side and letting the binding update the other side), I usually break 100Mb, even though my code has not allocated anything new. My question is what this extra memory is and what I can do to control it. I have created a simple, reproducible example below:
Say I have a main window with the following contents:
<StackPanel Height="25" Orientation="Horizontal">
<TextBox UndoLimit="1" Name="TestWidth" />
<Label>,</Label>
<TextBox UndoLimit="1" Name="TestHeight" />
</StackPanel>
And then in this window's constructor, I generate a new window, show it, and then bind it's WidthProperty and HeightProperty dependency properties to variables that utilize INotifyPropertyChanged:
public partial class MainWindow : Window, INotifyPropertyChanged
{
private int _WidthInt;
public int WidthInt
{
get { return _WidthInt; }
set { _WidthInt = value; NotifyPropertyChanged("WidthInt"); }
}
private int _HeightInt;
public int HeightInt
{
get { return _HeightInt; }
set { _HeightInt = value; NotifyPropertyChanged("HeightInt"); }
}
public MainWindow()
{
InitializeComponent();
Window testWindow = new Window();
testWindow.Show();
Binding bind = new Binding("HeightInt");
bind.Source = this;
bind.Mode = BindingMode.TwoWay;
testWindow.SetBinding(Window.HeightProperty, bind);
//bind.Converter = new convert();
//this.TestHeight.SetBinding(TextBox.TextProperty, bind);
bind = new Binding("WidthInt");
bind.Source = this;
bind.Mode = BindingMode.TwoWay;
testWindow.SetBinding(Window.WidthProperty, bind);
//bind.Converter = new convert();
//this.TestWidth.SetBinding(TextBox.TextProperty, bind);
}
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(string sProp)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(sProp));
GC.Collect();
}
}
Then if I constantly resize the window, my memory usage in the task manager linearly increases with no apparent upper limit. The program starts at 17Mb, and within 30 seconds of resizing it increases to 20Mb and hovers after a certain point in the low 20's (thanks Ian). This actually happens even if there are no bindings, and the memory does not go back down. While annoying, this isn't the "memory leap" I'm talking about.
If I uncomment the lines that also bind the textboxes to the variables, I get the following result: in just a few seconds it jumps from 18Mb to 38Mb and then hovers there (Please note setting the binding for the textbox in the XAML does not affect the memory spike). I tried implementing my own converter for the text box binding, but this does not affect the memory usage.
The jump still exists if I change the variables to new dependency properties and bind to them, e.g.
public static readonly DependencyProperty WidthIntProperty = DependencyProperty.Register("WidthIntProperty", typeof(int), typeof(MainWindow), new UIPropertyMetadata(0, null));
int WidthInt
{
get { return (int)this.GetValue(WidthIntProperty); }
set { this.SetValue(WidthIntProperty, value); }
}
...
Binding bind = new Binding("Text");
bind.Source = TestHeight;
bind.Mode = BindingMode.TwoWay;
this.SetBinding(MainWindow.HeightIntProperty, bind);
testWindow.SetBinding(Window.HeightProperty, bind);
or if I bind directly between the text property and the width dependency property and use BindingMode.OneWay or vise versa.
Using a CLR profiler does not seem to show me what's being allocated and I don't have access to a commercial memory profiler. Can someone explain to me what is being kept in memory and how I can get rid of it while still having the functionality of a continuous BindingMode? Do I have to implement my own binding method and do the event handling myself? Or is there something I can regularly flush outside of the GC?
Thank you for your time.
One thing to remember with simple programs like this is that a small amount of code can end up hitting a fairly large amount of WPF's infrastructure. E.g., with a single TextBox you're using the layout engine, the property engine, the templating system, the styling system, and accessibility features. The moment you start to type, you also bring in the input system, the typography support, and some non-trivial internationalization infrastructure.
Those last two may well be a large part of what you're seeing in this particular example. WPF automatically exploits a lot of OpenType font features, which requires it to do a lot of work under the covers. (As it happens the default UI font doesn't actually do a lot with it, but you still end up paying the price of entry for the code that discovers that Segoe UI is not a very interesting typeface.) It's a comparatively expensive feature for saying how subtle a difference it makes. Likewise, it's amazing how much goes into locale-aware input handling - getting that comprehensively right with full i8n support is more work than most people imagine.
You'll probably pay the price for each of these subsystems eventually, because the TextBox is not the only piece of WPF to use them. So the effort required for hand-built solutions that attempt to avoid them may ultimately be for nothing.
Tiny test applications paint a misleading picture - in a real application the price payed is shared out a bit better. Your first TextBox might have cost your 30MB, but you've now paged in a load of stuff that the rest of your application was going to use anyway. Had you started with an application that uses nothing but a ListBox, you could then add a TextBox and compare the difference in memory consumption to the ListBox-only baseline. This would probably give you a rather different picture of the marginal cost of adding a TextBox to your application.
So outside of the context of a trivial test application, the effort required to write your own text box is likely to produce very little difference in private working set in practice. You'll almost certainly end up paging in all of the features and systems I mentioned in the first paragraph eventually, because TextBox is not the only thing in WPF to use them.
Could each of these systems be more frugal? No doubt they could, but sadly, WPF hasn't had as much engineering input as I'd like, what with the distraction that is Silverlight, not to mention the rumours that yet another attempt at a UI framework is coming in Win8... High memory usage is, unfortunately, a feature of WPF. (Although bear in mind that a WPF app will also tend to use more memory on a machine with more memory. It takes some memory pressure before its working set gets driven to its most efficient level.)
I'm really embarrassed about this... I thought I had checked everything and tried as many approaches as I could think of, but I didn't think the memory spike was from the TextBox itself. That's what causes the spike. If you remove all of the bindings and fluff and just have the TextBoxes, even with their UndoLimit set to zero and limiting the MaxLength, the program's memory still spikes by 15Mb+ after a dozen or so edits of the TextBox's contents. So because the bindings also updated the Textbox, they triggered this spike. I know default controls have to cover a wide variety of uses, but as my first C#/WPF program, I didn't realize how bloated they actually are in this case. I'm off to write my own TextBox Control and to remind myself to never assume too much when it comes to this. But hey, at least I can put my custom binding code to the side now!

StatusBar not always updating

I am relatively new to MVVM, and I am trying to code up a basic Status Bar for an MVVM WPF application. I think I have the gist of things, but for some reason, the status bar does not always update, and I am not sure why.
In my ViewModel, I have a basic property that I update when I change a status message:
public string StatusMessage
{
get { return _statusMessage; }
set
{
if (value == _statusMessage) return;
_statusMessage = value;
base.OnPropertyChanged(() => this.StatusMessage);
}
}
My OnPropertyChanged method (which I have in a base ViewModel class that implements INotifyPropertyChanged) looks like so (got this idea from Gunther Foidl; wish I could claim credit for it because I think it's slick but I'm not quite that smart):
protected virtual void OnPropertyChanged<T>(Expression<Func<T>> exp)
{
MemberExpression me = exp.Body as MemberExpression;
string propName = me.Member.Name;
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propName));
}
}
At any rate, this all works great for all of my controls except one. On my MainWindow.xaml file, I have a StatusBarItem control bound to the above property, like so (the rest of the XAML has been trimmed for space reasons):
<StatusBarItem Grid.Column="0">
<TextBlock TextTrimming="CharacterEllipsis" Text="{Binding Path=StatusMessage}" />
</StatusBarItem>
When I run my application (which hits a couple of DBs in addition to generating a document from template and a bunch of other fairly resource-intensive stuff), some, but not all, messages show up on the status bar. I have debugged and verified that the messages all make it into the StatusMessage property, above (and the ensuing private variable), they just don't seem to be refreshing in the UI.
I have looked at several examples that use BackgroundWorker instances for ProgressBar controls, but haven't seen any for StatusBarItem controls, and am not really sure how to translate one to the other.
I have also used Tasks before in previous C# 4.0 and WPF apps, and figure it's probably a good way to go, but I haven't really been able to figure out how/where to designate the UI task (I've always done it in the code-behind for the MainWindow before, but I'm striving for a zero-code-behind to stay in keeping with MVVM here).
I'm pretty sure that a multi-threaded approach is the way to go; I just don't know enough about one approach (I know a little bit of this and a little bit of that) to make it work. I did see a couple of posts that used the older threading approach directly, but I pretty much stayed away from multithreading programming until I started using Tasks with .NET 4.0 (finding them a little easier to comprehend and keep track of), so I had a bit of trouble making sense of them.
Can anyone take pity on me and point me in the right direction, or suggest further debugging I can do? Thanks!
1)Reflection based binding can be source of error sometimes because of inlining. Try to see what happens if you notifypropertychanged with simple string instead of reflection.
2) if you are using multi threads there maybe a chance that you setup StatusMessage not from UIThread in that case it won't be able to update UI, you could invoke setter code on UI Dispatcher to see if that helps
3) check whether binding works , in constructor of xaml form modify StatusMessage directly on VM and see whether the change is shown on UI without invoking multithreaded service calls which introduce additional variables to simple textblock - string binding
4) if that doesn't help you could create a simple xaml form with single textblock bind it to your big viewmodel and see what happens, if nothing works you can begin cutting VM class to make it simpler so binding eventually starts to work and you find an error
5) if you think that statusbar is the problem see if single textblock without statusbar (extract xaml part from your example) works
Somewhere the notification does not get through.
I would try :
Add a dummy valueconverter on the textbinding so you can set a breakpoint and see if you are called
Dispatching the property set to set the value at a "better" time - that is sometimes nessesary.
Dispatching the set might do the trick.

Xaml parsing and multithreading

I'd like to load Xaml from code running in a background thread.
I understand I would have to sync with the dispatcher. However, it fails (throws an exception).
Why?
Here is the code
public MainWindow()
{
InitializeComponent();
Thread thread = new Thread(new ThreadStart(delegate
{
Dispatcher.Invoke(new Action(delegate
{
Content = XamlReader.Parse(
"<Button xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
Content='Hello World'/>");
}));
}));
thread.Start();
}
As Pavlo mentioned, you need to also set your content within the Dispatcher.
However, I will say - this is fairly useless.
Remember, when you call Dispatcher.Invoke or BeginInvoke, you're explicitly saying to run that code on the UI thread. By starting a background thread that does nothing but invoke back to the UI thread, you're effectively doing the same work on the UI thread, with the disadvantage of extra overhead being added to the system as well as harder debugging. In this case, you should just load the file directly.
This seems like a bad idea for a couple reasons. Are you expecting to get XAML fragments from a database or some other storage and you can't create the instances of these controls in C#? You could just create a Button directly.
Are you able to allow the data to drive your visualization? A good example of this is having a collection of ICommand objects (CommandViewModel, RelayCommand, etc) and a CommandView that you want to use to represent your command? In this case, it could be a <Button> with a binding to the CommandViewModel Title or Content property.
You're background thread could then be used to drive the population of data (collections, properties) and you're UI would be designed to flexibly accommodate the expected data patterns.

WPF: how to signal an event from ViewModel to View without code in codebehind? [duplicate]

This question already has answers here:
How can I Have a WPF EventTrigger on a View trigger when the underlying Viewmodel dictates it should?
(4 answers)
Closed 8 years ago.
I have quite simple (I hope :)) problem:
In MVVM, View usually listens on changes of ViewModel's properties. However, I would sometimes like to listen on event, so that, for example, View could start animation, or close window, when VM signals.
Doing it via bool property with NotifyPropertyChanged (and starting animation only when it changes from false to true) is possible, but it feels like a hack, I'd much prefer to expose event, as it is semantically correct.
Also, I'd like to do it without code in codebehind, as doing viewModel.myEvent += handler there would mean that I'd have manually unregister the event in order to allow View to be GC'd - WPF Views are already able to listen on properties 'weakly', and I'd much prefer to program only declaratively in View.
The standard strong event subscription is also bad, because I need to switch multiple ViewModels for one View (because creating View every time takes too much CPU time).
Thank you for ideas (if there is a standard solution, a link to msdn will suffice)!
Some comments:
You can use the weak event pattern to ensure that the view can be GC'd even if it is still attached to the view model's event
If you're already switching multiple VMs in for the one view, wouldn't that be the ideal place to attach/detach the handler?
Depending on your exact scenario, you could just have the VM expose a state property which the view uses as a trigger for animations, transitions, and other visual changes. Visual state manager is great for this kind of thing.
This is something that I wrestled with as well...
Similar to what others are saying, but here is an example with some code snippets... This example shows how to use pub/sub to have a View subscribe to an event fired by the VM - in this case I do a GridView. Rebind to ensure the gv is in sync with the VM...
View (Sub):
using Microsoft.Practices.Composite.Events;
using Microsoft.Practices.Composite.Presentation.Events;
private SubscriptionToken getRequiresRebindToken = null;
private void SubscribeToRequiresRebindEvents()
{
this.getRequiresRebindToken =
EventBus.Current.GetEvent<RequiresRebindEvent>()
.Subscribe(this.OnRequiresRebindEventReceived,
ThreadOption.PublisherThread, false,
MemoryLeakHelper.DummyPredicate);
}
public void OnRequiresRebindEventReceived(RequiresRebindEventPayload payload)
{
if (payload != null)
{
if (payload.RequiresRebind)
{
using (this.gridView.DeferRefresh())
{
this.gridView.Rebind();
}
}
}
}
private void UnsubscribeFromRequiresRebindEvents()
{
if (this.getRequiresRebindToken != null)
{
EventBus.Current.GetEvent<RequiresRebindEvent>()
.Unsubscribe(this.getRequiresRebindToken);
this.getRequiresRebindToken = null;
}
}
Call unsub from the close method to prevent memory leaks.
ViewModel (Pub):
private void PublishRequiresRebindEvent()
{
var payload = new RequiresRebindEventPayload();
payload.SetRequiresRebind();
EventBus.Current.GetEvent<RequiresRebindEvent>().Publish(payload);
}
Payload class
using System;
using Microsoft.Practices.Composite.Presentation.Events;
public class RequiresRebindEvent
: CompositePresentationEvent<RequiresRebindEventPayload>
{
}
public class RequiresRebindEventPayload
{
public RequiresRebindEventPayload()
{
this.RequiresRebind = false;
}
public bool RequiresRebind { get; private set; }
public void SetRequiresRebind()
{
this.RequiresRebind = true;
}
}
Note that you can also set the constructor up to pass in a Guid, or some identified in, which can be set on Pub and checked on sub to be sure pub/sub is in sync.
imho yYand separated
state - to be able to move data back/forth between view <-> vm
actions - to be able to call onto view model functions/commands
notifications - to be able to signal to the view that something has happened and you want it to take a viewy action like make an element glow, switch styles, change layout, focus another element etc.
while is true that you can do this with a property binding, its more of a hack as tomas mentioned; always has felt like this to me.
my solution to be able to listen for 'events' from a view model aka notifications is to simple listen for data-context changes and when it does change i verify the type is the vm i'm looking for and connect the events. crude but simple.
what i would really like is a simple way to define some 'view model event' triggers and then provide some kind of handler for it that would react on the view side of things all in the xaml and only drop to code behind for stuff thats not do-able in xaml
Like adrianm said, when you trigger your animation off a bool property you are actually responding to an event. Specifically the event PropertyChanged which the WPF subsystem. Which is designed to attach/detach correctly to/from so that you don't leak memory (you may forget to do this when wiring an event yourself and cause a memory leak by having a reference active to an object which otherwise should be GCed).
This allows you to expose your ViewModel as the DataContext for the control and respond correctly to the changing of properties on the datacontext through databinding.
MVVM is a pattern that works particularly well with WPF because of all these things that WPF gives you, and triggering off a property change is actually an elegant way to use the entire WPF subsystem to accomplish your goals :)
A more general question to ask is: "Why am I trying to deal with this event in my ViewModel?"
If the answer has anything to do with view-only things like animations, I'd argue the ViewModel needs not know about it: code behind (when appropriate), Data/Event/PropertyTriggers, and the newer VisualStateManager constructs will serve you much better, and maintain the clean separation between View and ViewModel.
If something needs to "happen" as a result of the event, then what you really want to use is a Command pattern - either by using the CommandManger, handling the event in code behind and invoking the command on the view model, or by using attached behaviors in the System.Interactivity libs.
Either way, you want to keep your ViewModel as "pure" as you can - if you see anything View-specific in there, you're probably doing it wrong. :)

Resources