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

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.

Related

Avoid Prism AutoWireViewModel Creating the ViewModel Twice

Prism can create an unneeded ViewModel if you have a one-arg constructor on your view. I am trying to understand how this can be avoided, or, if I can design something to work differently. Here is what happens.
The XAML view declares ViewModelLocator.AutoWireViewModel:
mvvm:ViewModelLocator.AutoWireViewModel="True"
And the class declares two constructors:
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
}
public MainWindow(MainWindowViewModel viewModel)
{
InitializeComponent();
DataContext = viewModel;
}
}
There is a reason that I declare the one-arg constructor: it is because the ViewModel is serializable; and when deserialized, the view is constructed by explicitly invoking that constructor with the restored ViewModel. But the issue can happen in two ways.
First, when you invoke the one-arg constructor:
MainWindowViewModel viewModel = new MainWindowViewModel();
MainWindow window = new MainWindow(viewModel);
Then Prism constructs the view, and that invokes the ViewModelLocator from the XAML, which creates and sets a ViewModel ... And then your explicit argument is set; replacing the auto-created instance (or if you reverse the lines in the constructor, than your explicit argument is actually wiped off).
AND, perhaps unexpectedly, or perhaps by some folly in my understanding, or some other unknown design aspect, it ALSO will happen if you resolve the view from the Container --- you might do this expecting to invoke the default constructor for the view; but that in fact does not happen; and, once again you will create two ViewModels:
MainWindow window = Container.Resolve<MainWindow>();
This line of code actually begins by discovering the one-arg constructor on the View, and then RESOLVING a ViewModel and invoking that constructor ... which again triggers the XAML auto-ViewModel; and then your one-arg constructor continues to wipe off the auto-ViewModel ...
It's consuming resources; and in fact, I tripped an exception where the view was binding based on some other state that was inconsistent with the ViewModel that I was expecting to explicitly be set.
I can't see a way to defeat the auto-created instance, and so I am not seeing how to invoke a one-arg constructor around the AutoWireViewModel behavior; or, how to resolve the view from the Container and avoid two ViewModels being created.
Perhaps resolving the View from the Container is abuse if it hasn't been registered, but the one-arg constructor seems to be reasonable, and it creates two instances ...
Is there some way? [Perhaps you can customize that behavior to check for an existing DataContext and then not set it if present ... or something along those lines?]
I created a simple example on GitHub:
https://github.com/steevcoco/PrismAutoCreatesViewModelTwice
To be clear here, Prism isn't creating the ViewModel twice. You are. You do it once in the code behind with the ctor, and you do it again with the ViewModelLocator. Pick one approach and use it. There is no need to have two different ways of setting the VM on the same View.
You should read up on containers and how they work. That will help your understanding of what is going on here. Every thing is working exactly as it should.
Well, for what it's worth, I have actually implemented a custom ViewModelLocator that works around this behavior. It is somewhat crude: it simply first checks if the current DataContext is non-null; and if so, the AutoWire will not create or set a Viewmodel.
I have updated the code in the repository for anyone interested.

Why Commands are taken from ViewModel Class?

I've just finished watching "Practical MVVM by Joel Cochran" video explaining MVVM, and i didn't understand a key problem.
In the video Joel explaining that the View is unaware of the ViewModel, but still the button is bound to a command within the ViewModel, so every time the button get pressed, the command action is performed.
My question is how the View is unaware of the ViewModel if I need to specifically bind the button to the ViewModel command like:
private ICommand _searchByNameCommand;
public ICommand SearchByNameCommand
{
get
{
if (_searchByNameCommand == null)
{
_searchByNameCommand = new RelayCommand(
p => this.LoadRealEstateCollectionByName(),
p => { return !String.IsNullOrEmpty(this.SearchOwnerName); }
);
}
return _searchByNameCommand;
}
}
And in the xaml:
<Button Content="Search"
Grid.Column="2"
VerticalAlignment="Center"
Command="{Binding SearchByNameCommand, Mode=OneWay}" />
SearchByNameCommand is defined in the ModelView.
The answer is the following:
Using MVVM, a view is tightly coupled to a view-model via it's DataContext.
The reason why the view is tightly coupled to its view-model is because the view must specify the specific names of observable properties and commands that are contained within its DataContext. That function alone introduces tight coupling.
RANT:
I'm not sure if I agree with a view being completely ignorant of its view-model dependency.
Think about it. A view is bound to the state and operations of its data context (aka view-model). In other words, it is tightly coupled to the state of the view-model but not the view-model its self?
What's the point?
So how useful is it to hide the view-model from the view if the view relies completely on its Data Context (i.e. the observable state and the exposed commands of the view-model)?
I think you somewhat misunderstood what "being unaware" actually means in this context. In winforms programming, when you had a button and wanted to subscribe to the click event, you had to attach an event handler, for instance
myButton.Click += new EventHandler(myButton_Click);
As you can see, that's the tight coupling. You're coupling specific instances together.
With commands in WPF however, there's a pretty big difference, because you don't say this instance handles this. You're saying I have these methods and properties (ViewModel) and I need these things to work properly (View). You can swap instances as you like, as long as they provide the things needed for proper functioning of the view. BUT, you don't care about attaching/detaching handlers, setting manually text values etc. That's all taken care by binding that happens automatically for you. Your View doesn't really know about the specific instance. All it knows is what data and actions it works with. ViewModel doesn't really care either how those data are displayed or dealt with.
That's why I don't actually agree with Scott Nimrod's answer. This is not tight coupling, but rather loose coupling (at least in my opinion). Tight coupling would be when you couldn't change one without affecting the other and that's obviously false in MVVM. That's the point actually, to have things coupled as least as possible. If you want to see tightly coupled components, look at winforms.

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.

What is the worst gotcha in WPF?

I've started to make myself a list of "WPF gotchas": things that bug me and that I had to write down to remember because I fall for them every time....
Now, I'm pretty sure you all stumbled upon similar situations at one point, and I would like you to share your experience on the subject:
What is the gotcha that gets you all the time? the one you find the most annoying?
(I have a few issues that seem to be without explanation, maybe your submissions will explain them)
Here are a few of my "personnal" gotchas (randomly presented):
For a MouseEvent to be fired even when the click is on the "transparent" background of a control (e.g. a label) and not just on the content (the Text in this case), the control's Background has to be set to "Brushes.Transparent" and not just "null" (default value for a label)
A WPF DataGridCell's DataContext is the RowView to whom the cell belong, not the CellView
When inside a ScrollViewer, a Scrollbar is managed by the scrollviewer itself (i.e. setting properties such as ScrollBar.Value is without effect)
Key.F10 is not fired when you press "F10", instead you get Key.System and you have to go look for e.SystemKey to get the Key.F10
... and now you're on.
Always watch the output window for
binding errors. Ignoring the output
window is a recipe for tears.
Use PresentationTraceOptions.TraceLevel="High" in a binding to get verbose binding information when debugging binding failures.
Make static, unchanging resources such as brushes PresentationOptions:Freeze="True" to save resources at runtime.
Use the WPF DataGrid as a datagrid. Modifying it to behave like Excel is a massive pain in the butt.
BindingList<T> does not play well with CollectionViewSource. Expose ObservableCollection<T> from your viewmodels instead.
The internet supplies half a dozen different ideas for displaying CueBanner text in a WPF textbox. They are all broken.
1) One that used to get me every half an hour when I was making my transition from WinForms: use TextBlock instead of Label when putting random text on the UI (or don't use any tag at all, if the text is static)!
2) DataTriggers/Triggers can't be put into Control.Triggers, but have to go into Control.Styles/Style/Style.Triggers
3) Property's type must implement IList, not IList<T>, if the property is to be recognized by XAML as a collection property.
4) Bindings capture exceptions.
5) Use singleton converters/static converter class, so you don't have to create a new converter every time you use it.
6) A type for default value of DependencyProperty has to be clearly specified: 0u as uint, (float) 0 as float, 0.0 as double...
7) It matters if the control's property definitions are before or after its content.
8) NEVER use PropertyMetadata to set a default value of reference type DependencyProperty. The same object reference will be assigned to all instances of the owning class.
When first starting out, the main gotchas that would get me would be
Lists not updating due to forgetting
to use ObservableCollection
Properties not being updated either
forgetting to add OnPropertyChanged
or incorrectly typing the property
name
Recently I have stumbled across these issues
Application failing to start due to
corrupt font cache
StringFormat localization issues
If enabled, Button.IsCancel assigns false to Window.DialogResult but Button.IsDefault no.
They are so similar and for me it seemed intuitive at first that both should close dialog. I usually break MVVM and fix this in code-behind
Button.IsCancel + Command = Dialog won't close (Window.DialogResult left unassigned) but Command executes
As I understand it: If IsCancel had higher priority than Command then on Esc it would assign 'false' to DialogResult and Command won't be called. Or, if Command would have higher priority then it would be called first and DialogResult would be assigned. I don't understand how it is skipped?
Binding swallows exceptions!
It not only steals time while debugging it is also wrong from the OOP point of view because if exception is thrown it means that something exceptional had happened somewhere in our system (anything from wrong data supply to unauthorized access to memory failure) so it can be handled only if you know what to do. You can't just catch(Exception){} catch 'em all and then ignore. If there is unknown exception in program it should notify user, log and close not pretend like everything is ok...
HeaderContent can have only one child control and has no padding
Everything should have padding even logical controls (containers), right? I think it is inconsistent. What do you think?
If you set focus to ListBox via FocusManager.FocusedElement you still won't be able to switch it's content with keyboard because focus is set to ListBoxes frame not it's content. I think I don't know other UI API that would expose something like controls frame to UI programmer it should be encapsulated from us because abstractly ListBox represents a list, it is just a list of things not a list of things in a box. ok it has box in its name but still... We almost have two different controls here.
MVVM not breaking fix
ListBox.IsSynchronizedWithCurrentItem by default is false so if you assign different value or null to ItesSource then SelectedItem still holds old value until user selects something from a new list. It could mess up CanExecute for example. Need to set it every time by hand.
No binding exposed in PasswordBox results in time waste and dirty hacks... But still it has a string property PasswordBox.Password exposed so don't even try to argue about security because Snoop...
It is not a gotcha but table layout is so IE6 IMO. Container design helps separate content from its layout.
Because every time I need to change something in places I need to mess up with Grid.Row and Grid.Column. Yes, we have DockPanel, StackPanel and others but you can't do some column alignment inside of them. (And DockPanel is like completely separate gotcha) If UniformGrid would be more customizable it would be ideal I think. You always need to choose between Grid and Panels and usually if you gain something you loose something else.
I got a pretty nifty one last week:
When Templating a RichTextBox, the event handling inside the template follows a strange route that has nothing to do neither with tunnelling nor bubbling
e.g.: In the case of an event that is supposed to tunnel: the event first tunnels through the ContentPresenter, then it tunnels back from the top of the template.
see my question on the subject
ToolTips and ContextMenus not sharing the DataContext of its owner? I think that gets everyone at first
There is no clean way to handle validation in WPF, I am not a fan of magic string which IDataErrorInfo offers by default:
public string this[string columnName]
{
if (columnName == "FirstName")
{
if (string.IsNullOrEmpty(FirstName))
result = "Please enter a First Name";
}
}
However, I have tried many frameworks like SimpleMVVM, FluentValidation and MVVMValidation and BY FAR MVVM Validation is the best getting to do stuff like:
Validator.AddRule(() => RangeStart,
() => RangeEnd,
() => RuleResult.Assert(RangeEnd > RangeStart, "RangeEnd must be grater than RangeStart");
My personal favorite is this one:
public double MyVariable
{
get { return (double)GetValue(MyVariableProperty); }
set { SetValue(MyVariableProperty, value); }
}
public static readonly DependencyProperty MyVariableProperty = DependencyProperty.Register(
"MyVariable", typeof(double), typeof(MyControl), new UIPropertyMetadata(0));
Try it, once this property is declared it will crash. Why? Because 0 can't be assigned to a double using reflection apparently.
Not really a gotcha but an advice: Use Snoop or something similar, if you don't use it you must be crazy ... Crazy i tell ya!
Binding.StringFormat only works if the type of the target property is string.
TreeView's SelectedItem property is not settable. Instead you have to bind TreeViewItem's IsSelected property to your item's viewmodel and set your selection there.
ListBox's SelectedItem, on the other hand is settable, but item selection is not equal to item focus. If you want to implement proper keyboard navigation along with selecting items from within viewmodel, you have to implement manual focus fix, like:
public void FixListboxFocus()
{
if (lbFiles.SelectedItem != null)
{
lbFiles.ScrollIntoView(lbFiles.SelectedItem);
lbFiles.UpdateLayout();
var item = lbFiles.ItemContainerGenerator.ContainerFromItem(viewModel.SelectedFile);
if (item != null && item is ListBoxItem listBoxItem && !listBoxItem.IsFocused)
listBoxItem.Focus();
}
}
...and call it every time you change selected item from viewmodel:
SelectedFile = files.FirstOrDefault();
viewAccess.FixListboxFocus();

MVVM ICommand alternative

I have begun creating a wpf mvvm app. It seems a vital ingredient to the ViewModel is a bunch of ICommands to have a loosely coupled way of allowing the view to interact with the viewmodel.
My question is this, why can't I bind directly to a method?
I have used Josh Smith's RelayCommand implementation of ICommand that allows you to inject delgates into an ICommand object, but really, is there some easier way to allow a button push to call a method in the viewmodel?
I'm new to MVVM, I believe I need some enlightenment
You can't bind directly to a method because Button (for example) doesn't have a property that accepts a delegate. Instead, it has a Command property of type ICommand. A RelayCommand (aka DelegateCommand) is just an ICommand that wraps delegates.
I see no technical reason why it wouldn't be possible for the view to bind to specific methods on the view model by way of a markup extension:
<Button Command="{ViewModelMethod SomeMethodName}"/>
However, this would be slower and would increase the coupling between the view and view model. If the view knows only about a property on the view model of type ICommand, the implementation of that command could change completely (or methods could be renamed) without the view being aware.
I completely disagree.
The speed of invocation bears no relevance: commands are user interactions, they never require speed.
Argument about coupling is flawed too. How come {Binding MyProperty} is not coupling but {ViewMethod MyMethod} is?
Requirement of having specially crafted 'Commands' to be wrapped around methods is a silly one. Commands might be useful implementation under the cover, but we already have methods in C# and replacing them with something big and bulky is not right.
And that thing about MarkupExtension and Binding, it really is difficult. But it can be done. Actually, it is done, you can have a look at MethodCall project on CodePlex:
http://methodcallthing.codeplex.com/
You can use binding to choose 'this' for the method, and can use binding to fetch arguments. And all those are live, i.e. being calculated at the time the command is invoked. Another bonus feature is push-out result of method call, you can use binding for that too (OneWayToSource).
ICommand gives you CanExecute, which is needed for control enabling. A simple delegate does not. ICommand is the way to go.
Apparently Microsoft needed a Command to be something first-class, probably because they felt having the CanExecute was necessary for most applications. I disagree and think the CanExecute should have just been another DependencyProperty that you would bind to a property of your viewmodel, but hey, what do I know?
Possibly they also thought that there was a need to decouple the implementation of a command from the control's datacontext. Yet again this seems unnecessary to me because the logic should live near the data that is being operated on, as is a fundamental principal of OO.
Personally I avoid using commands in MVVM because of the mess you have to create to implement them. I just let the view's code-behind delegate events up to the viewmodel.
Due to the way in which the title of this question is worded, readers might arrive here looking for an alternative to ICommand, instead of just a way to bind a UI action directly to a method of a viewModel. (Which is of little value, since it leaves open the question of what to do with the 'CanExecute` part.)
The use of ICommand is problematic in and of itself because it is defined in Windows.Input, which means that in order to declare ICommands in your ViewModels you have to reference WPF and the kitchen sink from within your application logic, and once you have done that, any noob might notice that MessageBox and a vast array of other GUI functionality is available, and might start making use of it, resulting in a terrible mess of mixed application logic and presentation logic.
So, if you want to get rid of using System.Windows, then you need to get rid of ICommand, and if you want to get rid of ICommand, then you might be happy to know the following:
WPF (specifically, the XAML designer) does not require your viewModels to statically expose instances of the ICommand interface.
By statically here I mean that the designer does not need to be able to prove, during design time, using reflection, that your command objects implement the ICommand interface; instead, WPF checks at runtime to make sure that UI actions are bound to objects which do in fact turn out to implement ICommand.
So, in your viewModels (application logic) instead of the ICommand interface of WPF you can be using some Command interface of your own device, and all you need to ensure is that the class that you will be instantiating at runtime to implement your Command interface also implements ICommand to keep WPF happy. This way you can avoid including ICommand from within your ViewModels, and subsequently you might be able to avoid having to reference System.Windows in your application logic.

Resources