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

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.

Related

How to use MainWindow as ShellViewModel View?

I understand that by default CM will look for ShellView in Views folder to use as ShellViewModel View but I want to use the MainWindow instead... can this be done and how?
How it Works
CM uses a set of View/ViewModel Naming Conventions, generally speaking, if you have a ViewModel named FooViewModel CM will attempt to locate a type with a similar name of FooView or FooPage.
What if you really want "MainWindow" and "ShellViewModel"?
If you just wanted to use an existing "MainWindow" with an existing 'root viewmodel' then consider subclassing Bootstrapper<TRootModel> and override OnStartUp. This is a prescribed method, but can seem daunting.
(I have not tested this code.)
protected override void OnStartup(object sender, StartupEventArgs e)
{
var rootModel = IoC.Get<TRootModel>();
var rootView = new MainWindow();
ViewModelBinder.Bind(rootModel, rootView, this);
rootView.Show();
}
The above method, of course, would only apply to the initial view for the root view model shown during start-up. Future attempts to display a view for ShellViewModel may work, or they may result in errors, I am not certain.
Extending Conventions
There are a few ways to customize the convention itself. The most flexible and direct method is to intercept/hook Caliburn.Micro.ViewLocator.LocateForModelType, this allows you to modify the behavior/strategy applied during view location.
private static void CustomViewLocatorStrategy()
{
// store original implementation so we can fall back to it as necessary
var originalLocatorStrategy = Caliburn.Micro.ViewLocator.LocateForModelType;
// intercept ViewLocator.LocateForModelType requests and apply custom mappings
Caliburn.Micro.ViewLocator.LocateForModelType = (modelType, displayLocation, context) =>
{
// implement your custom logic
if (modelType == typeof(ShellViewModel))
{
return new MainWindow();
}
// fall back on original locator
return originalLocatorStrategy(modelType, displayLocation, context);
};
}
The above can be called from inside a Bootstrapper<TRootModel>.Configure override:
protected override void Configure()
{
CustomViewLocatorStrategy();
base.Configure();
}
This method is more likely to play well with CM (in terms of any view caching, namely.) However, it still breaks conventions, and it's still a fair amount of code.
Registering Additional Suffixes?
One thing I want to point out, but have not had a chance to play with, is ViewLocator.RegisterViewSuffix implementation. I believe if you executed ViewLocator.RegisterViewSuffix(#"Window") then you could rely on CM to map MainViewModel to MainWindow.
This would allow for more expressive suffixes (such as Window, Dialog, Form, or others you may want to use.) Personally I dislike the use of 'View' as a suffix, I believe it's too generic (after all, they are all Views.)
Caliburn.Micro doesn't look for ShellView by default, this is how things work. Let's say you have a bootstrapper defined like this:
class MyBootsrtapper : Bootstrapper<MyViewModel> { }
Then CM (Caliburn.Micro) will look for a view named MyView. So yes you can use MainWindow instead as long as your view model name is MainWindowViewModel.
I have answered the other question you have asked and it seems you don't fully comprehend CM so i really really advise you to Start Here and you can always check the projects Documentation on codeplex because it contains all updated information and documentation.
Edit:
Caliburn.Micro uses a simple naming convention to locate Views for
ViewModels. Essentially, it takes the FullName and removes “Model”
from it. So, given MyApp.ViewModels.MyViewModel, it would look for
MyApp.Views.MyView.
Taken from official documentation here.

WPF - Custom Control + ICommand (How do I Implement this)?

Basically, I have a custom control FooControl.
public class FooControl : ItemsControl
{
//Code
}
I need to add some event handling, but rather than using a RoutedEvent I'd much more prefer to use Commanding instead. I'm not really sure how to go about doing this though. If I want it so that when Bar1Property (DependencyProperty) changes it raises the Execute associated execute property. I looked at the ButtonBase code through .NET Reflector and wow, that looks overly complicated. Is adding a command this complex?? Obviously I'd also have to make it so that my control enables/disables certain parts of itself depending on if the CanExecuteChanged is altered or not. But I guess that's another portion.
Here is my OnBar1Changed function so far...
private static void OnBar1Changed(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
FooControl element = (FooControl)obj;
//What to do here?
}
It sounds like by the way you are asking your question, you want to support commanding in your custom control (like for example Button supports). To do this you I recommend looking at how ICommandSource is implemented. Microsoft gives a great walk through on how you can implement it yourself:
http://msdn.microsoft.com/en-us/library/ms748978.aspx
At the simplest level, all you really need is something like:
FooControl element = obj as FooControl;
if (element == null) return;
if (element.MyCommand != null && element.CanExecute(this.CommandParameter)
{
element.MyCommand.Execute(this.CommandParameter);
}
You'd have to create Dependency Properties for both the Command and the CommandParameter, as well.
Hope that helps,

Easy way to make Silverlight combo boxes perform like HTML select boxes?

I'm fairly new to Silverlight but experienced in web development, and I'm finding myself highly annoyed with Silverlight's default combobox. It seems to be lacking any concept of use for regular data entry. Primarily I'm wishing it would function like an HTML select box, where you can hit the drop down, then type a letter and it takes you down to the first item with that letter. Is there an easy way I'm missing to make it function like this, or a third party control that can do this?
Thanks!
You could write an attached behavior to provide this functionality. The problem is that the items in a ComboBox in Silverlight aren't always strings. They may be entire controls that the user has templated as the ItemTemplate. If you know yours are going to be string you can implement a Behavior<ComboBox> to attach to the KeyDown event and select the correct one.
public class HTMLSelectBehavior : Behavior<ComboBox>
{
protected override void OnAttached()
{
AssociatedObject.KeyDown += OnKeyDown;
}
private void OnKeyDown(object sender, KeyEventArgs e)
{
SelectedItem = AssociatedObject.ItemsSource
.FirstOrDefault(i => i.ToString().BeginsWith((char)e.Key));
}
}
This is off the top of my head so it may not be exactly right and definitely lacks many safety checks, but it should give you an idea.

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

Custom WPF command pattern example

I've done some WPF programing and one thing I never got was the command pattern. Every example seems to be for built in ones, edit, cut, paste. Anyone have an example or suggestion of best practice for custom commands?
Ah ha! A question I can answer! Firstly, I should mention that I have personally found it easier to define and hook up commands in code rather than in XAML. It allows me to hook up the handlers for the commands a little more flexibly than an all XAML approach does.
You should work out what commands you want to have and what they relate to. In my application, I currently have a class for defining important application commands like so:
public static class CommandBank
{
/// Command definition for Closing a window
public static RoutedUICommand CloseWindow { get; private set; }
/// Static private constructor, sets up all application wide commands.
static CommandBank()
{
CloseWindow = new RoutedUICommand();
CloseWindow.InputGestures.Add(new KeyGesture(Key.F4, ModifierKeys.Alt));
// ...
}
Now, because I wanted to keep the code all together, using a code only approach to Commands lets me put the following methods in the class above:
/// Closes the window provided as a parameter
public static void CloseWindowExecute(object sender, ExecutedRoutedEventArgs e)
{
((Window)e.Parameter).Close();
}
/// Allows a Command to execute if the CommandParameter is not a null value
public static void CanExecuteIfParameterIsNotNull(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = e.Parameter != null;
e.Handled = true;
}
The second method there can even be shared with other Commands without me having to repeat it all over the place.
Once you have defined the commands like this, you can add them to any piece of UI. In the following, once the Window has Loaded, I add command bindings to both the Window and MenuItem and then add an input binding to the Window using a loop to do this for all command bindings. The parameter that is passed is the Window its self so the code above knows what Window to try and close.
public partial class SimpleWindow : Window
{
private void WindowLoaded(object sender, RoutedEventArgs e)
{
// ...
this.CommandBindings.Add(
new CommandBinding(
CommandBank.CloseWindow,
CommandBank.CloseWindowExecute,
CommandBank.CanExecuteIfParameterIsNotNull));
foreach (CommandBinding binding in this.CommandBindings)
{
RoutedCommand command = (RoutedCommand)binding.Command;
if (command.InputGestures.Count > 0)
{
foreach (InputGesture gesture in command.InputGestures)
{
var iBind = new InputBinding(command, gesture);
iBind.CommandParameter = this;
this.InputBindings.Add(iBind);
}
}
}
// menuItemExit is defined in XAML
menuItemExit.Command = CommandBank.CloseWindow;
menuItemExit.CommandParameter = this;
// ...
}
// ....
}
I then also later have event handlers for the WindowClosing and WindowClosed events, I do recommend you make the actual implementation of commands as small and generic as possible. As in this case, I didn't try to put code that tries to stop the Window closing if there is unsaved data, I kept that code firmly inside the WindowClosing event.
Let me know if you have any follow up questions. :)
I blogged about a bunch of resources on WPF Commands along with an example last year at http://blogs.vertigo.com/personal/alanl/Blog/archive/2007/05/31/commands-in-wpf.aspx
Pasting here:
Adam Nathan’s sample chapter on Important New Concepts in WPF: Commands
MSDN article: The Command Pattern In WPF
Keyvan Nayyeri: How to Add Commands to Custom WPF Control
Ian Griffiths: Avalon Input, Commands, and Handlers
Wikipedia: Command Pattern
MSDN Library: Commanding Overview
MSDN Library: CommandBinding Class
MSDN Library: Input and Commands How-to Topics
MSDN Library: EditingCommands Class
MSDN Library: MediaCommands Class
MSDN Library: ApplicationCommands Class
MSDN Library: NavigationCommands Class
MSDN Library: ComponentCommands Class
Also buried in the WPF SDK samples, there's a nice sample on RichTextBox editing which I've extended. You can find it here: RichTextEditor.zip
In the September 2008 edition of the MSDN magazine, Brian Noyes has a excellent article about the RoutedCommand/RoutedEvents!!!
Here is the link:
http://msdn.microsoft.com/en-us/magazine/cc785480.aspx
The thing about XAML is that it is fine for 'simple' programs, but sadly, it doesn't work well when you want to do things like share functions. Say you have several classes and UI's all of which had commands that were never disabled, you'd have to write a 'CanAlwaysExecute' method for each Window or UserControl! That's just not very DRY.
Having read several blogs and through trying several things, I've made the choice to make XAML purely about looks, styles, animation and triggers. All my hooking up of event handlers and commanding is now down in the code-behind. :)
Another gotcha by the way is Input binding, in order for them to be caught, focus must be on the object that contains the Input bindings. For example, to have a short cut you can use at any time (say, F1 to open help), that input binding must be set on the Window object, since that always has focus when your app is Active. Using the code method should make that easier, even when you start using UserControls which might want to add input bindings to their parent Window.

Resources