Setting Command Bindings via XAML on PageFunction forms - wpf

If you are creating a WPF window or a WPF page, you can bind commands to functions within the XAML.
<Page x:Class="WpfPageApplication.Page1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:WpfPageApplication="clr-namespace:WpfPageApplication"
Title="Page1" Background="LightGray"
>
<Page.CommandBindings>
<CommandBinding
Command="WpfPageApplication:PizzaCommands.ConfigurePizza"
Executed="OnConfigurePizza" />
</Page.CommandBindings>
There is another type of WPF form: a PageFunction. But it doesn't let you type:
<PageFunction.CommandBindings>
I can guess two possible explanations:
Because PageFunction is a generic object, you have to somehow enter the generic parameters into the XAML.
It's just an inconsistency in the framework.
Does anyone know how I can configure the CommandBindings for a PageFunction within the XAML? (I know I can do it in the code, but that's not the point).

PageFunction ultimately derives from Page, so I'm fairly certain you can just use <Page.CommandBindings> to define your command bindings. Certainly you can use <Page.Resources> in a PageFunction to define its resources.
Why can't you use <PageFunction.CommandBindings>? I don't know, but I think you're probably right when you say it has to do with the fact that PageFunction is a generic type. You'd need some way in XAML to say what the underlying type is. I think that's possible in the .NET 4.0 version of XAML but not in the current version.

Related

How to supply a design time value for silverlight textblock that is bound to viewmodel property?

I have a TextBlock in my XAML that has its text bound to a property in my viewmodel.
<TextBlock x:Name="SomeText" Text="{Binding TheTextProperty}" />
This works fine, but at design time, there is no viewmodel so the property is unresolvable and the text is blank. This is hard to work with in the designer because it shows no visible text.
How can I specify some default text to use at design time?
Maybe you could try
<TextBlock x:Name="SomeText" Text="{Binding TheTextProperty, FallbackValue='Some other text'}" />
as documented here.
You can also use Design Time Data to provide a rich binding experience in your solution. Its a little hard to set up and get running, but here's the gist.
First, you create your DataContext in xaml. Add a new Xml document to your solution (the root is a good place) and give it an .xaml extension. Lets call this file "foo.xaml" for this example.
In this file, remove all of the XML and start creating an instance of your DataContext type. For example, if your DataContext was a string (very simple example) your file would look like the following:
<string xmlns="clr-namespace:System;assembly=mscorlib">LOL!</string>
You might have yours look like
<ViewModel xmlns="clr-namespace:MyNamespace">
<ViewModel.MyObservableCollection>
<MyModel Name="foo" />
<!-- etc -->
Set the Build Action on this file to DesignDataWithDesignTimeCreatableTypes:
Next, in your View, add the following namespaces and properties to the root of your Window/UserControl:
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DataContext="{d:DesignData Source=foo.xaml}"
Source is relative to the current document. So, if your solution looked like
Views
MyUserControl.xaml
Data
foo.xaml
you would set the Source to ../Data/foo.xaml.
There are other ways to create a DesignData context depending on whether your ViewModel can be instantiated at design time, etc.
Another option is to use the DesignerProperties.GetIsInDesignMode function to determine if the control is hosted in VS/Blend and Generate a fake DataContext in that case. Laurent Bugnion provides a number of examples of how to create and use design-time data in this post

Using custom control's alias in XAML

In a WPF (Silverlight) UserControl I have lots of custom control instances:
<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:My="clr-namespace:MyProject;assembly=MyAssembly" Name="uc1" >
...
<Grid x:Name="grid1">
...
<My:CustControl x:Name="name1" />
<My:CustControl x:Name="name2" />
<My:CustControl x:Name="name3" />
...
</Grid>
In MyProject I have not only the CustControl implemented, but also the CustControl1, the CustControl2, the CustControl3 and the like. Sometimes, I have to use another custom control type in the UserControl. Can I have only one place for changing custom control's name instead of changing it in all the numerous references in the XAML?
In other words, can I use an alias for those multiple custom control references inside my XAML and one place where I define the real CustomControl class' name for that alias?
Or maybe some other approach for solving this problem?
You could write a simple empty wrapper class, which would inherit the control you currently use. Then in XAML you would use this wrapper instead of the specific CustControl. At any time, you could change the base class for the wrapper at one single place.
But I must say: this design stinks. Are you sure you couldn't solve this issue with global styles/templates for one CustControl class?

Making a DataTemplate blendable

How can I make a Datatemplate for a ViewModel blendable (designable in expression blend). When I go to resources and try to edit the DataTemplate directly all I see on the Drawingborad is a blank rectangle. This is because the DataTemplate is not bound to anything. Of course I can create a UserControl and create some designtime data in code there to see the template but I now would have to switch back and forth between the resource (to edit) and the usercontrol (to see the result of my edit). Isn't there a more direct way to edit and see my DataTemplate?
It's a bit of a stretch to use, but Blend has a feature called "Design-Time Data" that can help you out. It's tough to get started at first, but once you do a few it's pretty easy. It kind of forces you into a nice pattern for DataContext as well.
Here's a good link on the subject: http://www.robfe.com/2009/08/design-time-data-in-expression-blend-3/
Here's a few choice excerpts:
On Design-Time Sizes
...design time properties can be
safely ignored by other tools and they
are ignored at the runtime
(mc:Ignorable specifies that the
namespace with the "d" prefix can be
ignored).
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Expression Blend uses two design time
properties (d:DesignWidth,
d:DesignHeight) to specify a size for
a control to be used at design time...
On Design-Time Data Sources
I stumbled across d:Datacontext when I
was playing with Blend 3 and tried
adding a “live datasource” to my
window. I thought it was going to
behave just like the old way of
setting a DataContext, but when I ran
my application, there was no data! ...
So the upshot is, now we can write
code like this:
...
<Grid ...
DataContext="{StaticResource GameDataSource}"
d:DataContext="{StaticResource DesignTime_DateDataSource}">
Note that this is for Blend 3 if you want first-party support for these features. They are pretty good - there's even a designer for the design-time data, though I've not looked into those features yet.
Applying To DataTemplates
This is something I sorta made up, but it seems to work. Here I'm using the Design-Time data feature to pull data into the visual element's d:DataContext. You'd have to do this for every top-level element that needed a DataContext set.
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<!-- Resource dictionary entries should be defined here. -->
<DataTemplate x:Key="MyTemplate">
<TextBlock Text="{Binding Text}" d:DataContext="{StaticResource SampleDataSource}" />
</DataTemplate>
</ResourceDictionary>
The binding syntax is a little bit more explicit if you are using a DataTemplate with a DataType set, but it still works:
<DataTemplate DataType="{x:Type vm:MyViewModel}" >
<TextBlock Text="{Binding Text}"
d:DataContext="{Binding Source={StaticResource SampleDataSource}}" />
</DataTemplate>
This strategy will allow you to see how the DataTemplate will work while editing it directly, however you won't be able to see the result on any view that utilizes that DataTemplate unless you actually run the app. This is a limitation of Blend at the moment due to the fact that they don't appear to be using Mocks, but rather complete replacement objects. If blend ever adds the ability to create a new fake data source by clicking on "New DataSource -> Based on Referenced Object -> MyCustomerObject", then you will be in business.
It's possible you could overcome this limitation with some attached property trickery of your own, but it would be difficult at best.
Alternative
An alternative that will work in every situation, but is a bit more cumbersome to setup is setting up StaticResources that swap out fake data for real data during runtime, but in the designer show static sample data.
Here's a really great article by Karl Shifflett that includes some of these techniques and a few videos on it:
http://karlshifflett.wordpress.com/2008/10/11/viewing-design-time-data-in-visual-studio-2008-cider-designer-in-wpf-and-silverlight-projects/
Hope this helps,
Anderson
This strategy will allow you to see
how the DataTemplate will work while
editing it directly, however you won't
be able to see the result on any view
that utilizes that DataTemplate unless
you actually run the app. This is a
limitation of Blend at the moment due
to the fact that they don't appear to
be using Mocks, but rather complete
replacement objects. If blend ever
adds the ability to create a new fake
data source by clicking on "New
DataSource -> Based on Referenced
Object -> MyCustomerObject", then you
will be in business.
If I want to use acutal ViewModel mocks I guess it is the best way to create actual ViewModel instances and the references them with d:DataContext (e.g. using a ObjectDataProvider or x:Static)

Using XAML + designer to edit Plain Old CLR Objects?

I want to write a POCO in XAML, and use a DataTemplate to display that object in the GUI at runtime. So far, so good; I know how to do all that.
Since I'll already have a DataTemplate that can transform my POCO into a WPF visual tree, is there any way to get the Visual Studio designer to play along, and have the Design View show me the POCO+DataTemplate's resulting GUI, as I edit the POCO's XAML? (Obviously the designer wouldn't know how to edit the "design view"; I wouldn't expect the Toolbox or click-and-drag to work on the design surface. That's fine -- I just want to see a preview as I edit.)
If you're curious, the POCOs in question would be level maps for a game. (At this point, I'm not planning to ship an end-user map editor, so I'll be doing all the editing myself in Visual Studio.) So the XAML isn't WPF GUI objects like Window and UserControl, but it's still not something where I would want to blindly bang out some XAML and hope for the best. I want to see what I'm doing (the GUI map) as I'm doing it.
If I try to make a XAML file whose root is my map object, the designer shows "Intentionally Left Blank - The document root element is not supported by the visual designer." It does this even if I've defined a DataTemplate in App.xaml's <Application.Resources>.
But I know the designer can show my POCO, when it's inside a WPF object. One possible way of accomplishing what I want would be to have a ScratchUserControl that just contains a ContentPresenter, and write my POCO XAML inside that ContentPresenter's Content property, e.g.:
<UserControl ...>
<ContentPresenter>
<ContentPresenter.Content>
<Maps:Map .../>
</ContentPresenter.Content>
</ContentPresenter>
</UserControl>
But then I would have to be sure to copy the content back out into its own file when I was done editing, which seems tedious and error-prone, and I don't like tedious and error-prone. And since I can preview my XAML this way, isn't there some way to do it without the UserControl?
I'm doing this right now, actually. Create a ResourceDictionary and reference it from the other XAML file. For example, make one file containing you plain old object, i.e.:
<Windows:ResourceDictionary>
<Collections:ArrayList x:Key="PreferenceList">
<NumericPreference id="server.port"
helpText="The port on which the server should listen for incoming connections (default is 30588)"
min="1"
max="65535"
step="1"
displayName="Port"
validationName="Port number" />
</Collections:ArrayList>
</Windows:ResourceDictionary>
(where NumericPreference is replaced by your POCO), and then reference it like so:
<UserControl>
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Preferences.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<!-- Your code here -->
</Grid>
</UserControl>
... But yes, you'd still need your "scratch user control" hooked up to it to see the designer result, but there's no copying and pasting involved. The key part here is the ResourceDictionary Source="YourStaticResource.xaml"
You can't have the map as the root element (the root element must be ResourceDictionary), but you can have it as the only child element of the ResourceDictionary.
To reference the resource, use, of course {StaticResource XXX} or {DynamicResource XXX} where XXX is the x:Key you gave the POCO in its XML file (in this case I gave the referenced POCO object, the ArrayList, the "PreferenceList" key)
I'm fairly certain that you aren't going to get what you want here.
WPF won't process much in the way of logic in the design window. That includes (for the most part) DataTemplate and IValueConverter objects that you use in your XAML data bindings, since those objects usually work with (POCO) objects that are not instantiated until run-time.
This could explain why it works in the UserControl example, since you ARE clearly creating an instance of your Map POCO right there in the XAML. The designer window absolutely will not attempt to render anything that is based on bindings or templates that refer to objects that Visual Studio can't instantiate at design-time. This basically means that you can't have your objects show up in the design window if you are trying to create those objects in your C# (or whatever) code behind the scenes. Your back-end code cannot be run by the design window, because it has to be built by the compiler and run before any of it can execute. (Previous versions of Visual Studio use extreme workarounds to try and remedy this, and Microsoft no longer provides this support.) Markup languages like XAML don't have that restriction since they contain no logical execution sequence, so the design window can render them on the screen using only the parsed XAML markup.
In a nut-shell, I don't think the XAML design window was ever intended to be used the way you are trying to use it.
If you really want to be able to see your POCO in the designer, but you don't want to have to insert it into a UserControl with a ContentPresenter --- try deriving your POCO from an appropriate root-element that the designer can render, and adding a Serialize method to read/write it to/from files.
If these solutions don't work for you, then you are probably going to have to deal with Visual Studio not rendering your Map objects in the design window. Maybe this will give you some motivation to create that stand-alone map editor after all, even if you don't ship it out to the end-user. You may want to spend the time to write a simple editor, even if it's for your use only. Visual Studio won't replace your custom map editor - at least, not in any way that will be useful to you.

Why can a WPF/Silerlight XAML file parse without the default namespace?

I read that "the default namespace is important because otherwise the XAML parser will not recognize the elements".
However, just as a test, I take it out and, although the visual designer cannot recognize the element names anymore, this Silverlight XAML runs just fine:
<UserControl x:Class="Second12.Page"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<Grid x:Name="LayoutRoot" Background="White">
<TextBlock Text="This is a test."/>
</Grid>
</UserControl>
Why is that?
I would look at it being reasonable for the Silverlight parser to fall back to the WPF silverlight parsing by default.
you would get errors if you used wf xaml or even WPF xaml not supported by Silverlight parser.
I would look at the importance of having the namespace going forward though.
XAML is a language supported currently by WPF, Silverlight which uses a subset of WPF, and WF and a little bit in WCF. each of those have their own Parsers right now.
With .net 4.0 there will be system.xaml.dll or something to that effect. The namespace will mean quite a bit more as it will direct the parser further. WPF, WF, and WCF will all be using that parser, and would guess that silverlight in the future will use it.
edit, primarily the top level namespaces are used to provide intellisense schema in the way that parser is written for each group.
Perhaps the sentence ought to have read "should not recognize". Its seems a reasonable fallback position for the XAML parser to assume the no-name namespace contiains XAML elements in the absence of a default namespace definition.

Resources