Accessing the WebContext class in XAML - silverlight

The generated App.xaml.cs file contains this
private void Application_Startup(object sender, StartupEventArgs e)
{
// This will enable you to bind controls in XAML files to WebContext.Current
// properties
this.Resources.Add("WebContext", WebContext.Current);
but I cannot figure out how to refer to this object. It seems like I ought to set the page DataContext = "WebContext" and then use it like this
... property="{Binding Path=User.IsAuthenticated}
I'm sure it's straightforward. Can someone clue me in?
Well done, and of course I can't believe I didn't see that. With the addition of a value converter suddenly a tangled mess of state management code becomes declarative, showing and hiding various UI elements according to whether the user is logged in or in various roles without me having to litter my code with trivial conditionals at myriad logical inflection points.

Try:-
property="{Binding Path=User.IsAuthenticated, Source={StaticResource WebContext}}"
that ought to find it. Its not an object you'd want directly assigned to the DataContext normally, the similarity of the names is co-incidental.

Related

WPF MVVM Where do you put UI Functions that wouldn't appear on your ViewModel

My understanding is that when you take your View and say:
myView.DataContext = myViewModel;
You are kind of assigning the class that it should refer to, almost like the code-behind in a most apps. I've always loved the design but where is the best place to put display type logic that really doesn't belong in your view model? For example say you're modifying a context menu for an item depending on the item's status. In the past I've handled different bits of display functionality with converters. I was going to use the Views native code behind but then I realized I don't think I have access to that do I?
Typically you would have a model object for each item in your list. Then wrap each model in a view model. The view model would then expose properties for the attributes you described (colors, fonts, etc.) and fire property change notifications. Hope that helps.
My assumption that setting the DataContext for a View was the same as pointing it to a different code behind file was incorrect. The DataContext is used for binding purposes. You can still reference methods in the normal code behind like so:
<CheckBox Margin="5,0,30,0"
x:Name="OSHPD" IsChecked="{Binding OSHPD}"
Validation.ErrorTemplate="{x:Null}" Checked="OSHPD_Checked" Unchecked="OSHPD_Unchecked">OSHPD Approval</CheckBox>
private void OSHPD_Checked(object sender, RoutedEventArgs e)
{
FM.IsEnabled = false;
}
private void OSHPD_Unchecked(object sender, RoutedEventArgs e)
{
FM.IsEnabled = true;
}
Databinding IsChecked="{Binding OSHPD}" is hitting the ViewModel while the events Checked="OSHPD_Checked" Unchecked="OSHPD_Unchecked" reference the Views code behind.
Most things that go in a View's code behind could also go in a ValueConverter, Behavior or AttachedProperty. Each of these will be able to access Control level properties. Generally you are able to supply these with values like the colours/brushes/shapes and other view specific data, to keep the valueConverter/behaviour/AttachedProperty generic if you did find you needed to reuse it.

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.

How to properly use a Subclassed silverlight control?

I created this class where I wanted to override this specific event for the content control.
public class MyContentControl : ContentControl
{
protected override void OnKeyUp(KeyEventArgs e)
{
//do something
//..........
e.Handled = true;
}
}
However when I am using this control in my XAML everything compiles and works fine, but I am getting a runtime exception and I am not sure exactly why? Could someone point me in the right directions....
The exception I get is
XamlParseException
UPDATED (Shows where abouts of the exceptions)
In the XAML I have:
xmlns:ctrls="clr-namespace:SilverlightProject.CustomControls"
and I use it like:
<ctrls:MyContentControl Grid.Column="0" x:Name="_contentControl" VerticalAlignment="Center" HorizontalAlignment="Center" />
Content controls require a default template to be created somewhere (e.g. in generic.xaml). They do not have a matching XAML file like user controls.
If you can provide more information, I can show you how to create an appropriate template.
There are many reasons for this.
To start with. Give the fully qualified namespace.
Instead of
xmlns:ctrls="clr-namespace:SilverlightProject.CustomControls"
Use
xmlns:ctrls="clr-namespace:SilverlightProject.CustomControls;assembly=YourAssebmlyName"
If that, doesn't help.
You directly attach your control with the application. Then, enable Debug -> Exceptions. Check Thrown option for the CLR execetion checkbox. You have fair amount of possibility to get to know the cause.

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 ;-)

Is there a way to bind the results of a public method in xaml.cs to a control in xaml?

Let's take a very simple example:
In my window1.xaml, i have a label
control named 'lblProduct'.
In my window1.xaml.cs, i have a
public method called
CalculateProduct(Int Var1, Int
Var2). CalculateProduct will, as
you may have guessed, calculate the
product of the variables passed in.
I'd like to simply bind the results of 'CalculateProduct' to my label. My actual use case is a little more complicated than this. However, if I could get this up and running not only would I be quite happy, I'd be able to figure out the rest.
I've seen interesting examples using the ObjectDataProvider to bind to a static method of a new class. While this is well and good, I don't feel the need to create a new class when I've already instantiated the one for my window. In addition, there may be other global variables that I'd like to take advantage of in my Window1 class.
Thanks for your time and help,
Abel.
It's quick and dirty but I'd probably just have CalculateProduct set a property with its result and databind to the property.
Yes, there is a way. It's not pretty. You have to add an xmlns:Commands attribute to your window1.xaml tag. I ended up bastardizing some code I found in this Code Project article.
Is the product that you want to display in the label something that's generated on load, or from another control event?
I'm not sure this will help you, but I ran into something similar where I was trying to generate XAML dynamically with XSLT. My solution worked, kind of...well, not really for what I was trying to do. But maybe it will help you.
As I said, you have to declare the xmlns in your page tag, like so:
<Page x:Class="WpfBrowserApplication1.Page1"
blah blah blah
xmlns:Commands="clr-namespace:WpfBrowserApplication1">
Then, define a static class in your application with the same namespace, pretty much the same as the example in the Code Project article, with handlers for a RoutedUICommand:
namespace WpfBrowserApplication1
{
public static class CommandHandlers
{
private static System.Windows.Input.RoutedUICommand _submitCommand;
static CommandHandlers()
{
_submitCommand = new System.Windows.Input.RoutedUICommand("Submit", "SubmitCommand", typeof(CommandHandlers));
}
public static void BindCommandsToPage(System.Windows.Controls.Page caller)
{
caller.CommandBindings.Add(new System.Windows.Input.CommandBinding(SubmitCommand, SubmitContact_Executed, SubmitContact_CanExecute));
}
public static System.Windows.Input.RoutedUICommand SubmitCommand
{
get { return _submitCommand; }
}
public static void SubmitContact_Executed(object sender, System.Windows.Input.ExecutedRoutedEventArgs e)
{
...do stuff...
}
public static void SubmitContact_CanExecute(object sender, System.Windows.Input.CanExecuteRoutedEventArgs e)
{
if (e.Source is System.Windows.Controls.Button)
e.CanExecute = true;
else
e.CanExecute = false;
}
}
}
The nasty part is that, so far as I've found, the only way to map things back to Page1.xaml is to cast the sender object and dig through the UI elements of the Page, similar to how you would dig through the DOM on a web page. I had some success with this, but certainly don't pretend to be an expert.
The last thing you have to do is wire up your control in the Page1.xaml.cs. In the XAML, you do it like so:
<Button Name="btnSubmit" Command="Commands:CommandHandlers.SubmitCommand" etc... />
In the code-behind, like so:
private void Page_Loaded(object sender, RoutedEventArgs e)
{
CommandHandlers.BindCommandsToPage(this);
}
I hope that helps, and good luck.
Why you not just set the label value in your CalculateProduct method before you return from the method. Basically way do you need data binding here? It is one way anyhow, since you are binding to a label.
ObjectDataProvider has an ObjectInstance property that you can assign your Window instance to.
aogan: The idea here is to leverage the flexibility of WPF databinding. I could set the entire UI in the code behind, but MS has developed this binding system and i wanted to easily take advantage of it. Also, this was a simple example for a more complicated problem.
To everyone else involved, i've gone with PITAdev's solution. Thanks for the help.

Resources