So you've got a usercontrol. You would like to bind to some of its dependency properties, so you need specify an x:Name in order to use it.
You can't do this...
<UserControl x:Class="WpfApplication1.UserControl1" x:Name="UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid />
</UserControl>
...because member names cannot be the same as their enclosing type.
So you need to pick something else... but what's a good convention to go for here? Stick something arbitrary on to the end? "UserControl1UserControl"? Call it "Root"? Use a different case "userControl1"?
What choices have you guys been making?
I know this is really minor, but I try to name elements very carefully and consistency is important to me.
Name it however you named the XAML file.
Foo.xaml:
<UserControl x:Name="foo" ...
Be descriptive; be consistent.
In other words, just pick something and stick to it.
These names end up as fields in your class, so I just use standard field naming conventions. And if it's the root-level control, I always call it "_root":
<UserControl x:Name="_root">
<StackPanel>
<TextBox x:Name="_nameTextBox"/>
<TextBox x:Name="_ageTextBox"/>
</StackPanel>
</UserControl>
Related
I have a grid that I am trying to hook up a visibility converter to. I have a class set up in the HelperObjects namespace, but for some reason the xaml is not picking up the reference. The error message is "The resource BoolToVisConverter could not be resolved" Why won't the xaml pull in this resource? I am sure I am doing something ridiculous here...
Here is the xaml:
xmlns:HelperObjects="clr-namespace:foo.HelperObjects"
...
<Grid Visibility="{Binding isZoneTwoVisible, Converter={StaticResource BoolToVisConverter}}">
The error message is indicating that the resource identified by the key BoolToVisConverter, to which you're trying to bind, cannot be found.
The most likely explanation is that you haven't declared that resource within a scope that can be accessed by your xaml. You'll want to create a StaticResource with a key matching the name you're referencing, within a Resources section of your xaml, the exact location may vary depending on your needs/structure.
Assuming you're doing this within a Window, you could do something like:
<Window>
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVis"/>
</Window.Resources>
<Grid Visibility="{Binding isZoneTwoVisible, Converter={StaticResource BoolToVis}}">
<--...Content...-->
</Grid>
</Window>
Note: I haven't included your namespace in front of the BooleanToVisibilityConverter because this is a class which already exists within the framework.
It may be the case you require slightly different behaviour, or don't have access to that class, in which case you may need to add your namespace when defining the resource, e.g. <HelperObjects:BooleanToVisibilityConverter x:Key="BoolToVis"/>
Potentially useful further info about static resources: https://learn.microsoft.com/en-us/dotnet/framework/wpf/advanced/staticresource-markup-extension
Try to specify the converter in UserControlResources or even parent level Grid Resources. Assuming you are using a UserControl.
And your code is unclear as of where you are defining the StaticResource BoolToVisConverter. But generally heres the process.
Look at this sample code below to define your StaticResorce in the UserControl Resources section. Make sure you set the DataContext where isZoneTwoVisible is residing. I am hoping you implemented ImplementINotifyPropertyChanged and said PropertyChanged on your isZoneTwoVisible or isZoneTwoVisible is a DependencyProperty. Note: BooleanToVisibilityConverter is a class that implements an IValueConverter or if your property is a bool you don't even need that class.
<UserControl.Resources>
<BooleanToVisibilityConverter
x:Key="boolToVisibility"></BooleanToVisibilityConverter>
</UserControl.Resources>
You did all the things said above and it still dosen't work, sometimes I specify the relative Source hoping its residing in a UserControl.
Visibility="{Binding isZoneTwoVisible,Converter={StaticResource boolToVisibility},RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl}}">
I have a binding to a parent-element. How can I provide the data type for the DataContext in the binding, so intellisense can resolve the bound Properties?
The binding works fine at runtime. So, I have the following XAML structure:
<TabControl Name="TabDynamic"
ItemsSource="{Binding TabItems, Mode=OneWay}" ...>
<TabControl.Resources>
<DataTemplate x:Key="TabHeader" DataType="TabItem">
<DockPanel>
<TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type TabItem}}, Path=Header}" />
<Button Command="{Binding ElementName=TabDynamic, Path=DataContext.DeleteTabCommand}"
CommandParameter="{Binding ElementName=TabDynamic, Path=DataContext.TabItems/}">
<Image Source="{DynamicResource DeleteImg}" Height="11" Width="11"></Image>
</Button>
</DockPanel>
</DataTemplate>
<DataTemplate x:Key="TabContent" DataType="viewModels:ConnectionInfoVM">
<views:BufferViewerControl/>
</DataTemplate>
</TabControl.Resources>
</TabControl>
The data type of the DataContext is "viewModels:ConnectionInfoVM".
Intellisense will now underline both Properties on the DataContext (so DeleteTabCommand and TabItems are underlined).
I already tried to use the design-time data-context definition "d:DataContext" within the Button element like so:
d:DataContext="{d:DesignInstance viewModels:ConnectionInfosVM}"
But this does not change the intellisense warnings.
I also tried to define the DataType on the DataTemplate to be "viewModels:ConnectionInfosVM", as I do for the content-template, but that too does not change the intellisense warnings (and I guess would be wrong, as the data type of the element really is a TabItem).
Another try was to define the DataContext by adding the following to the Button element definition:
<Button.DataContext>
<viewModels:ConnectionInfosVM/>
</Button.DataContext>
But this too, does not get rid of the warnings.
I found a solution at least for the above described problem. I was setting the DataContext of the window in question in the code-behind. The TabControl in my example just inherits that DataContext, which is a ConnectionInfosVM.
In order to fix those warnings (and of course for the gained flexibility in providing a DataContext by a Locator), I defined the DataContext in XAML like so:
<UserControl ...
DataContext="{Binding Source={StaticResource mainViewModelLocator}, Path=ConnectionInfosVM}">
It seems that intellisense is now able to resolve those references. But on the other side, I also changed the TextBlock contained within the DataTemplate to the following:
<TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type TabItem}}, Path=DataContext.Address}" />
Now the DataContext of such a TabItem is actually a different type, as it is the type of the backing object for the TabItem. So in this case, the Property Address cannot be found by intellisense.
So, the question kind of remains, is there a possibility to define the type of the DataContext within a binding defined in a DataTemplate?
I needed to add the mc:Ignorable="d" attribute to the Window tag. Essentially I learned something new. The d: namespace prefix that Expression Blend/Visual Studio designer acknowledges is actually ignored/"commented out" by the real compiler/xaml parser!
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
The following was taken from
Nathan, Adam (2010-06-04). WPF 4 Unleashed (Kindle Locations 1799-1811). Sams. Kindle Edition.
Markup Compatibility
The markup compatibility XML namespace (http://schemas.openxmlformats.org/markup-compatibility/2006, typically used with an mc prefix) contains an Ignorable attribute that instructs XAML processors to ignore all elements/attributes in specified namespaces if they can’t be resolved to their .NET types/members. (The namespace also has a ProcessContent attribute that overrides Ignorable for specific types inside the ignored namespaces.)
Expression Blend takes advantage of this feature to do things like add design-time properties to XAML content that can be ignored at runtime.
mc:Ignorable can be given a space-delimited list of namespaces, and mc:ProcessContent can be given a space-delimited list of elements. When XamlXmlReader encounters ignorable content that can’t be resolved, it doesn’t report any nodes for it. If the ignorable content can be resolved, it will be reported normally. So consumers don’t need to do anything special to handle markup compatibility correctly.
I'm trying to get into MVVM from a UWP perspective. Everything seems to work almost like on WPF, but I can't get a good ViewModel/View Mapping running.
According to the Microsodt-Specialist: https://channel9.msdn.com/Events/Build/2015/3-635 , starts arround 20 Minutes, there is some new special Syntax for the ResourceDictionaries. I've done all steps, which loads the Dictionary as expected, but the straightforward-mapping doesn't work:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:v="using:ARGUSnet.RaspberryPiFramework.Designer.Views"
xmlns:vm="using:ARGUSnet.RaspberryPiFramework.Designer.ViewModels"
xmlns:local="using:ARGUSnet.RaspberryPiFramework.Designer.Dictionaries"
x:Class="ARGUSnet.RaspberryPiFramework.Designer.Dictionaries.ViewModelMappingDict">
<DataTemplate x:Key="dtTest" x:DataType="vm:TestViewModel">
<v:TestView />
</DataTemplate>
</ResourceDictionary>
I think the problem herein lies in the fact, I have to define a Key. Although I found some explanations about this, I don't get why this has to be done nowadays.
Anyways, the mapping works, if I do this in the ViewContainer directly:
<Page.Resources>
<DataTemplate x:DataType="vm:TestViewModel">
<v:TestView />
</DataTemplate>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<ContentControl
Content="{Binding CurrentContent}" />
</Grid>
The problem is, all examples are found are working kinda directly, without an explicit Mapping-Dictionary, or work with Freamworks like mvvmlight.
Since this is more for learning purposes, I'd rather make this work without blackboxing the Binding-Mechanics into an Framework.
Is it possible, this is just a Bug in the ResourceDictionary? I also found this Thread, How to associate view with viewmodel or multiple DataTemplates for ViewModel? , but according to my understanding, the question there was about an runtime mapping, while I can bind directly.
is it possible to write something like this in XAML:
<DataTemplate DataType="{x:Type vm:EntityListViewModel<T>}">
BUT
I need to specify generics because the declaration is EntityListViewModel<T>.
May be use DataTemplateSelector.
There are some support for generics in xaml 2009
http://blogs.windowsclient.net/rob_relyea/archive/2009/06/01/xaml-using-generic-types-in-xaml-2009.aspx
But im not sure if that works with datatemplate.
You could however experiment with setting the DataType property from code... i havet tried that though :)
I have a XBAP application with the following user control:
<UserControl x:Class="XXX.UsersGrid"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="Auto" Width="Auto">
<UserControl.Resources>
<DataTemplate x:Key="UpArrowUsers">
<DockPanel>
<TextBlock Text="xxUser" x:Name="upArrowUsersHeader" HorizontalAlignment="Center"></TextBlock>
<Path x:Name="arrow" StrokeThickness = "1" Fill= "gray" Data= "M 5,10 L 15,10 L 10,5 L 5,10"/>
</DockPanel>
</DataTemplate>
</UserControl>
...
Now I want to fetch the string "xxUser" from a resx file which is embed as resource in the application
How do I achieve this?
I was able to do it in a program with:
<TextBlock VerticalAlignment="Center" Margin="3"
Text="{x:Static prop:Resources.OpenButton}"
Visibility="{Binding Source={x:Static prop:Settings.Default}, Path=ShowButtonText,
Converter={StaticResource BoolToVis}}"></TextBlock>
I also had to include the .Properties namespace in my xaml, like so:
xmlns:prop="clr-namespace:MyProjectNamespace.Properties"
This allowed me to not only use the string resources I had defined for my project for globalization, but I was also able to bind (two way) to my application's Settings. This let me very easily remember the window's position, size, etc. As you can see, use Settings. for settings, and Resources. for resources.
As Steven mentioned, I think the "official" way or the "best" way is to stick x:Uid on everything that you want to globalize, but I didn't and it worked with no problems. I think the x:Uid thing is mostly required if you are using automated tools or breaking the translation task up as you would in a large project. I just did all my own stuff manually in VS, so maybe it was ok.
Ben
Two more additional points that I forgot to mention above in "I was able to do it...":
You don't have to wrap the Properties.Resources object in your own. You can access it directly, as I have done in my example above. I think wrapping the object is a way to get the same result as I discuss in my 2nd point.
By default, the resource files are built with "ResXFileCodeGenerator". This makes them internal when it generates the code file, so xaml can't access it. You have to change this to "PublicResXFileCodeGenerator", which generates public classes. You can change this by clicking the resource file in the solution explorer and editing the "Custom Tool" property.
(sorry, I couldn't edit my above post because I was a temporary member at that time.)
Create a static class that makes the resources available as properties:
public static class Resources
{
public string Resource
{
return Properties.Resources.ResourceManager.GetString("Resource");
}
}
Then you can bind your TextBox to this:
<TextBlock Text="{Binding Source={x:Static local:Resources}, Path=Resource}" x:Name="upArrowUsersHeader" HorizontalAlignment="Center"
xmlns:local="clr-namespace:MY_NAMESPACE;assembly=MY_ASSEMBLY">
As Ben said, and I found an another tutorial.
The access modifier of Resources.resx should be changed from Internal to Public. I failed many times and after changing the access modifier to Public, it does work.
None of those answers are close to what you want. I'd start by reading about Localization in WPF. You'll find that if you are doing localization with WPF you'll want x:Uid defined on every node in your app.
http://msdn.microsoft.com/en-us/library/ms788718.aspx
I don't know if this can be done directly in XAML but if you write your own wrapper class around ResourceManager and use it instead. Notice that the class inherits from TextBlock:
public class ResourceContentTextBlock : TextBlock
{
public string ResourceName
{
set
{
this.Text = Properties.Resources.ResourceManager.GetString(value);
}
}
}
You can then use ResourceContentTextBlock in your XAML anywhere you would otherwise use a TextBlock:
<Window x:Class="WpfApplication3.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:client="clr-namespace:WpfApplication3"
>
<client:ResourceContentTextBlock ResourceName="String1" />
</Window>