I'm creating a WPF wizard control following the MSDN Structured Navigation example. My working XAML looks like this, where my WizardBase is a subclass of System.Windows.Navigation.PageFunction, and MyPageOne is a subclass of WizardBase (namespaces and class names changed for privacy):
<local:WizardBase
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:My.Namespace"
x:Class="My.Namespace.MyPageOne"
KeepAlive="True"
WindowTitle="Page One">
This works great: when I navigate to this page in the wizard, the dialog title changes to "Page One". But now I want to internationalize that string. So I changed it to:
WindowTitle="{Binding Source={x:Static local:LocalizedStrings.PageOneTitle}}"
which fails at runtime with:
A 'Binding' cannot be set on the 'WindowTitle' property of type 'MyPageOne'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject.
What's special about WindowTitle that it can be set but not bound? I'm assuming that I've just made some kind of novice error.
Oh, duh, it's really easy. I just want:
WindowTitle="{x:Static local:LocalizedStrings.PageOneTitle}"
That is, set it directly rather than applying via a binding. I was making it way too complicated...
Related
I am a newbie in WPF. I was exploring MVVM Pattern for WPF applications. I am having trouble in binding Text property of a TextBox from VIEW to a variable in VIEWMODEL
Here is the TextBox from MainWindow.xaml
<TextBox x:Name="UsernameTxt" Grid.Row="4" materialDesign:HintAssist.Hint="Username"/>
I just need to know how to bind its Text Property to ViewModel Class in Class Library
Thanks
I think it's possible to give a very generic answer to this very generic question.
If the question changes context this answer is very likely to be deleted but here goes anyhow.
You want your viewmodel to be in the datacontext of the textbox. Because datacontext is inherited down the visual tree this usually means you want to set datacontext of your window to an instance of the viewmodel. Or maybe the usercontrol your textbox is in, but we know nothing about your app so let's just cover the simple scenario.
Your options are to instantiate a viewmodel using code or xaml.
If you look at this article:
https://social.technet.microsoft.com/wiki/contents/articles/31915.wpf-mvvm-step-by-step-1.aspx
That instantiates in xaml.
Note the xmlns is
xmlns:local="clr-namespace:wpf_MVVM_Step01"
That's saying where you see some bit of markup which is prefaced "local:" then go get the class out of this namespace.
To point to a different dll ( a class library ) you need to tell it which assembly. You do that by adding ;assembly=Whicheverdll to your equivalent of that xmlns. And of course that won't be local then so give it a different name. You also need a reference to that dll or project added to the entry point exe.
Once you've done all that and your viewmodel is instantiated into memory and in the datacontext of that textbox you need some sort of binding.
Which the article covers but that will be something like:
<TextBox Text="{Binding YourPublicStringProperty}"/>
I have several PowerShell modules I've developed using WPF/XAML and one of them uses an example I found and used to bind a DataGrid ItemSource property to a variable called "resultsData":
<DataGrid Name="gridResults" ItemsSource="{DynamicResource resultsData}"/>
Then in the Window.Resources section of my XAML file there is a reference made to the data binding value:
<Window.Resources>
<x:Array x:Key="resultsData" Type="sys:Object"/>
</Window.Resources>
Finally, in PowerShell I can update the DataGrid's property as follows:
$uiHash.Window.Resources["resultsData"] = $uiHash.resultsHash
This works really well and I'm trying to replicate it in another project where I'm simply trying to bind the text property of a TextBlock using the Windows.Resources section in my XAML file. The problem is I have no idea what to put in that section to make it work.
I've tried using the same <x:Array> tag but it's obviously not an array. I've tried <x:Code> and <x:Null> and a multitude of other options which all result in a failure to load the window along with Visual Studio's visual designer barfing...
Could someone help me understand what to put in the Windows.Resources section to ensure I can reference these properties in PowerShell through the Window.Resources object?
The Text property of a TextBlock can be set to or bind to a string which is defined like this in XAML:
<sys:String x:Key="textResource">some text...</sys:String>
...where sys is mapped to the System namespace:
xmlns:sys="clr-namespace:System;assembly=mscorlib"
This is my first time ever doing anything with XAML and I'm a bit lost.
I'm trying to add a DataTemplateSelector to my XAML page using the instructions found here.
However I'm stuck on the part where I'm supposed to "declare the TaskListDataTemplateSelector as a resource". This is the example given:
<Window.Resources>
...
<local:TaskListDataTemplateSelector x:Key="myDataTemplateSelector"/>
...
</Window.Resources>
However, the top level tag in the XAML document is <UserControl>, and I don't see anything about Window or Window.Resources.
Under the <UserControl> tag is a <UserControl.Resources> tag, but when I try to put the example code there, it gives me an error saying "The namespace prefix 'local' is not defined". I tried replacing "local" with the actual namespace, but got the same error.
The custom DataTemplateSelector class is in the codebehind for the XAML page, and is in the same namespace.
For anyone who googled this question like I did:
I think I found the answer.
You need to define the local prefix in your XAML file.
This can be done by placing the following namespace argument in the root element:
xmlns:local="clr-namespace:AssemblyName"
Change "AssemblyName" in your erm.. assembly's name.
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
I'm using the new d:DesignInstance feature of the 4.0 series WPF tools. Works great!
Only issue I'm having is: how can I set properties on the instance? Given something like this:
<Grid d:DataContext="{d:DesignInstance plugin:SamplePendingChangesViewModel, IsDesignTimeCreatable=True}"/>
How can I set properties on the viewmodel, aside from setting them in its default ctor or routing it through some other object initializer?
I gave this a try but VS gives errors on compile "d:DataContext was not found":
<Grid>
<d:DataContext>
<d:DesignInstance IsDesignTimeCreatable="True">
<plugin:SamplePendingChangesViewModel ActiveTagIndex="2"/>
</d:DesignInstance>
</d:DataContext>
For the moment I'm going back to using a resource and 'd:DataContext={StaticResource SampleData}', where I can set the properties in the resource.
Is there a way to do it via a d:DesignInstance?
As #jberger you should probably use d:DesignData instead of inlining a d:DataContext.
However you can set the d:DataContext inline in the xaml file as well, the secret is to use the correct class (DesignProperties) to qualify the d:DataContext property:
<d:DesignProperties.DataContext>
<plugin:SamplePendingChangesViewModel ActiveTagIndex="2"/>
</d:DesignProperties.DataContext>
How do you know what class to qualify with? Mouse over a property that is set in attribute syntax and a tooltip will appear with the fully qualified property name.
Note also that im not using the d:DesignInstance markup exstension as its job specifically is to create a instance of a type that you provide the name for (or generate a proxy of that type if it cant be instanciated at design-time). Thats not what we want, we want to define the instance in inline xaml in this case.
Indeed, d:DesignData (also a markup extension) works much the same way, except that it looks for a xaml file and deserializes that to the actual instance to use instead of just using the default constructor.
Just for completeness i should also mention that you can use DesignData and DesignInstance with element syntax as well by using their full class names (xxxExtension):
<d:DesignProperties.DataContext>
<d:DesignDataExtension Source="SampleData.xaml"></d:DesignDataExtension>
</d:DesignProperties.DataContext>
This is true for most markup exstensions but its not required to follow this naming convension (The Binding class is a notable exception) More info can be found here:
Markup Extensions and WPF XAML