Detecting Design Mode using WPF in a Static Method - wpf

I am using WPF. I have a static class that performs some setup not available during design mode. This constructor gets called by a window in design mode, which results in an exception being thrown.
How do I detect design mode in a static method, so I can invoke the appropriate design mode behavior?
The recommended approach does not work for static methods.
Edit:
The static constructor is called from xaml, so I can't conditionally call it (unless I move the call to code-behind, which I'd like to avoid).
In the window: <Window ... HelpProvider.Keyword="some_help_topic.html">
In the class:
static HelpProvider()
{
// Load the .chm file from an application setting (this fails at design time)
// Add a WPF command binding
}

The possible way to solve it keeping attached property in xaml file is:
Move initialization code from static constructor to attached property changed callback. Frankly speaking, it is not good practice to do such kind of work in static constructors.
In your attached property changed callback you have a reference to your window. So you can call DesignerProperties.GetIsInDesignMode(yourwindow) there and decide, if you need to load file or whatever causes issues.

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.

Setter not getting called when using DoubleUpDown from the extended WPF toolkit

Has anyone used this control? Is there something I am missing? I created a WPF interface to tune a PID controller (just a line follower built from NXT) and I am trying to adjust my constants using the DoubleUpDown control, I can bind to the properties in my service no problem and see them so the getter is getting called but when I change values I never see the setter fire off (i.e. breakpoint never gets hit).
Any advice would be great!
Thanks...
Here is some code to go with this, this is just a normal dependency property - in this case value is getting assigned to a double that is part of the service (my datacontext) but that isn't any different from when I use an adapter at work on some boring business form - Lego's are way cooler...
public double Kp
{
get { return service.kp; }
set
{
service.kp = value;
OnPropertyChanged("Kp");
}
}
Even if there was a problem there (setting the field in the service) I should at least be able to put a break point at service.kp = value and see it trying to set it, and yeah - I will post this over at the wpf extended toolkit forum as well.
Make sure your constants are actual public dependency properties, or public properties on a class that implements the INotifyPropertyChanged interface. You should post this in the Discussions on the Extended WPF Toolkit project site. Also check your output window for any binding errors. Can you provide some code?
http://wpftoolkit.codeplex.com/
UPDATED:
Based on the code you provided in the Discussions section of rthe project site; you should bind the property to the Value proeprty of the DoubleUpDown control and not the Text.

WPF Application base class?

I'm not even sure if this is even possible, but I've just started WPF development on a few new projects and tried to wrap up some common functionality by creating a mini-framework. Just things like exception handling and thread management.
What I would like to do is replace this line...
public partial class App : Application
with
public partial class App : MyFrameworkApplication
I've got the libraries set up and referenced, but I get an error regarding the 'partially' declared App class, presumably because it's still referencing the old base class.
Any ideas? Thanks.
EDIT: #Jeff M: No, your solution didn't work. I suspect because the MyFrameworkApplication is actually in a library and the z namespace declaration fails to recognise the library's namespace. I've got it referenced in the App.xaml.cs, but the suspicious looking error is:
Error 3 Undefined CLR namespace. The 'clr-namespace' URI refers to a namespace 'MyLibraryNamespace' that is not included in the assembly.
I can circumvent the problem by creating a proxy class within the local namespace and having it derive from the library class...but it's a bit smelly.
I suspect it's because the the underlying XAML root is still an Application as opposed to MyFrameworkApplication. I'd guess the generated baml uses the root as it's parent class. Try changing it to the appropriate names.
e.g.,
<z:MyFrameworkApplication x:Class="MyNamespace.App"
...
xmlns:z="clr-namespace:MyNamespace">
...
</z:MyFrameworkApplication>
It seems my suspicions were correct.
From the docs in Code-Behind and XAML in WPF:
Code-behind, Event Handler, and Partial Class Requirements in WPF
The partial class must derive from the type that backs the root element. (emphasis mine)
Note that under the default behavior of the markup compile build actions, you can leave the derivation blank in the partial class
definition on the code-behind side. The compiled result will assume
the page root's backing type to be the basis for the partial class,
even if it not specified. However, relying on this behavior is not a
best practice.
The event handlers you write in the code behind must be instance methods and cannot be static methods. These methods must be defined by
the partial class within the CLR namespace identified by x:Class. You
cannot qualify the name of an event handler to instruct a XAML
processor to look for an event handler for event wiring in a different
class scope.
The handler must match the delegate for the appropriate event in the backing type system.
For the Microsoft Visual Basic language specifically, you can use the language-specific Handles keyword to associate handlers with
instances and events in the handler declaration, instead of attaching
handlers with attributes in XAML. However, this technique does have
some limitations because the Handles keyword cannot support all of the
specific features of the WPF event system, such as certain routed
event scenarios or attached events. For details, see Visual Basic and WPF Event Handling.
The root application type in code-behind and in the xaml must agree.

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. :)

WPF unit testing, UIElement.RaiseEvent, ArgumentException

I am trying to build out a unit test and would like to fake out a DropEvent.
I get an error as it is attempting to raise the event. I can't create a DragEventArgs is it protection level is internal.
System.ArgumentException : Object of type 'System.Windows.RoutedEventArgs' cannot be converted to type 'System.Windows.DragEventArgs'
I have the following...
[Test]
public void Test()
{
DesignerMock view = new DesignerMock();
_viewModel = (PanelDesignViewModel)view.DataContext;
view.Show();
Assert.IsNotNull(_viewModel);
RoutedEventArgs args = new RoutedEventArgs(DesignerCanvas.DropEvent,view.DesignerCanvas) ;
view.DesignerCanvas.RaiseEvent(args);
view.Close();
}
As ascalonx says, you shouldn't test your View, only your ViewModel. This means your ViewModel needs to be decoupled from the View. Instead of an event handler, expose a simple public method on the ViewModel that will do the work you need, and simply call this in your test. To make your View call this method, use an attached behavior. Caliburn has a nice "Actions" attached behavior to do just this.
You mention you also have some VisualTreeHelper stuff "going on". This is a violation of the M-V-VM pattern, as it couples your VM to a specific V implementation. What ever your doing there, abstract it out to a "service" interface and use IoC or Service Locator to provide this service to your VM. I might suggest looking at Onyx for this (disclaimer: I'm the author of this library). It provides a flexible and easy to use mechanism for providing services to your VM.
If you're adamant that you want to test your code in this way, you could use reflections to create a DragEventArgs. However, the real question, I think, is if you're going in the right direction with your unit testing. I usually avoid doing any testing directly on my Views and stick with testing the more easily testable viewmodels (if indeed you're using MVVM) because of exactly the issue you're having right now.

Resources