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}}">
Related
I've defined a style resouce in MainWindow.xaml as follows:
<Window.Resources>
<Style x:Key="PageHeader" TargetType="TextBlock">
...
I'm then trying to use it for a TextBlock element in a user control:
<TextBlock Style="{StaticResource PageHeader}">Welcome!</TextBlock>
However, I get the error:
The resource "PageHeader" could not be resolved.
There are no syntax errors in the style specification that I can see. The resolve error is all I get.
I've also tried setting the TargetType to an x:Type too to no avail. Any pointers here?
This is in two different files, right? It's out of scope. All user controls inherit from their visual parent is inherited dependency properties, like text formatting. DataContext is inherited, but appears not to be inherited by the same mechanism. Resources are not inherited.
Try putting the Style in App.xaml, or in a resource dictionary XAML file that's explicitly included in App.xaml. Everybody gets what's in App.xaml.
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.
In solving a problem around dynamic resources tonight, I ended up with a solution that relied on the ability of a Behavior class to participate in the resource hierarchy of it's associated framework element. For instance, consider the following
<Application>
<Application.Resources>
<system:String x:Key="TestString">In App Resources</system:String>
</Application.Resources>
</Application>
<Window>
<Window.Resources>
<system:String x:Key="TestString">In Window Resources/system:String>
</Window.Resources>
<Border>
<Border.Resources>
<system:String x:Key="TestString">In Border Resources</system:String>
</Border.Resources>
<TextBlock Text="{DynamicResource TestString}" />
</Border>
</Window>
The TextBlock will show the resource from the border. However, if I do this...
public void Test()
{
var frameworkElement = new FrameworkElement();
var testString = (string)frameworkElement.FindResource("TestString");
}
...it finds the one from the application because it is not part of the visual tree.
That said, if I instead do this...
public class MyBehavior : Behavior<FrameworkElement>
{
public string Value... // Implement this as a DependencyProperty
}
Then add it to the TextBlock like this...
<TextBlock Text="{DynamicResource TestString}">
<i:Interaction.Behaviors>
<local:MyBehavior Value="{DynamicResource TestString}" />
</i:Interaction.Behaviors>
</TextBlock>
The behavior does get the value of the resource and will track it dynamically. But how?
A Behavior is not a FrameworkElement so you can't call SetResourceReference on it, nor is it part of the Visual Tree so even if you could call SetResourceReference, it still wouldn't find resources local to the FrameworkElement. Yet that's exactly what a Behavior does. How?
Put another way, if we wanted to write our own class that also exhibited those same behaviors (no pun intended), how would one insert itself into the resource hierarchy of the visual tree?
Well, I think I found it! The secret is a Freezable. Simply put, when you add a Freezable to the resources of a FrameworkElement, any DependencyProperties on that Freezable which are assigned a DynamicResource will properly resolve.
Using this knowledge, I've created a DynamicResourceBinding that lets you use it like any other DynamicResource but with the added advantage of being able to specify a converter, format string, etc.
Here's a link to that page here on StackOverflow where I do this for both Dynamic and Static resources...
Post 33816511: How to create a DynamicResourceBinding
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>
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>