How to set tooltip for user control (from style file) - wpf

I created my control which looks like that
<UserControl BorderBrush="#A9C2DE" HorizontalAlignment="Left" x:Class="WPFDiagramDesignerControl.Components.UcWBSBlock"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="86" Width="151" >
<UserControl.Resources>
<ResourceDictionary Source="Tooltip.xaml"/>
</UserControl.Resources>
<Grid x:Name="MainGrid">
<TextBox Name="txtBox" Style="{StaticResource DefaultStyle}" >
</TextBox>
</Grid>
I also have a file with style for tooltip "Tooltip.xaml"
How can I use this style for entire UserControl?
Usually I did this with that code
<TextBox ToolTip="{StaticResource tooltipname}"/>
But it was easy because file with style was in resource dictionary of control where I placed textbox. However I can't do sth like that
<UserControl BorderBrush="#A9C2DE" HorizontalAlignment="Left" ToolTip="{StaticResource tooltipname"}/>
Because at this point my style isn't in resource dicionary yet.
I was trying to use this syntax
<UserControl.ToolTip> </UserControl.ToolTip>
but I don't konow how should I refer to static resource
Maybe it is lame question but I just don't konow how to do it :)

One option is to just use DynamicResource instead of StaticResource to defer the lookup until runtime and then use the attribute syntax:
<UserControl ... ToolTip="{DynamicResource tooltipname}" ...
You can also write the StaticResourceExtension using element syntax so that you can write it after the Resources section:
<UserControl.Resources>
<ResourceDictionary Source="Tooltip.xaml"/>
</UserControl.Resources>
<UserControl.ToolTip>
<StaticResourceExtension ResourceKey="tooltipname"/>
</UserControl.ToolTip>

Related

Only last icon in XAML shown when icon used from resources

when I try to use a material design icon from the icon pack that is defined in the ResourceDictionary, only the first icon in XAML is rendered at run time. I've followed an example that can be found here.
Example follows:
App.xaml:
<Application x:Class="TestWpf.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TestWpf"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<materialDesign:BundledTheme BaseTheme="Light" PrimaryColor="DeepPurple" SecondaryColor="Lime" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml" />
<ResourceDictionary Source="pack://application:,,,/TestWpf;component/Dictionary1.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
Dictionary1.xaml:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes">
<materialDesign:PackIcon x:Key="CashIcon" Kind="Cash" />
</ResourceDictionary>
MainWindow.xaml:
<Window x:Class="TestWpf.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="450" Width="800">
<StackPanel>
<Button Content="{DynamicResource CashIcon}" />
<Button Content="{DynamicResource CashIcon}" />
<Button Content="{DynamicResource CashIcon}" />
</StackPanel>
</Window>
And the result is a window that looks like this:
In xaml editor all buttons have icons on them, as expected:
Why is this happening and, more important, how to fix this?
P.S. We've found out that if you create two Cash icons in the ResourceDictionary and apply each to a button, then they will both be shown but again, only once, you can't have say 3 buttons and 2 icons in ResourceDictionary.
one more solution is to use a non-shared resource (x:Shared Microsoft docs)
<materialDesign:PackIcon x:Key="CashIcon" Kind="Cash" x:Shared="False"/>
x:Shared Attribute: When set to false, modifies WPF resource-retrieval behavior so that requests for the attributed resource create a new instance for each request instead of sharing the same instance for all requests.
A scenario for x:Shared="false" is if you define a FrameworkElement or FrameworkContentElement derived class as a resource and then you introduce the element resource into a content model. x:Shared="false" enables an element resource to be introduced multiple times in the same collection (such as a UIElementCollection). Without x:Shared="false" this is invalid because the collection enforces uniqueness of its contents. However, the x:Shared="false" behavior creates another identical instance of the resource instead of returning the same instance.
The PackIcon type is a Control. An element in the visual tree in WPF can only have a single parent. In other words, the pack icon is still a single instance added as child of the first button, then moved to the second, then to the third. You will in fact have to create multiple instances of the pack icon.
Instead of creating resources, you could use the PackIcon markup extension.
<StackPanel>
<Button Content="{materialDesign:PackIcon Cash}"/>
<Button Content="{materialDesign:PackIcon Cash}"/>
<Button Content="{materialDesign:PackIcon Cash}"/>
</StackPanel>
Depending on your actual scenario, you could alternatively create a DataTemplate, which will automatically create instances of the pack icons for each button.
<DataTemplate x:Key="CashPackIconTemplate">
<materialDesign:PackIcon Kind="Cash" />
</DataTemplate>
<StackPanel>
<Button ContentTemplate="{StaticResource CashPackIconTemplate}"/>
<Button ContentTemplate="{StaticResource CashPackIconTemplate}"/>
<Button ContentTemplate="{StaticResource CashPackIconTemplate}"/>
</StackPanel>

Avalonia Ui equivalent to ImageResource

I try to define an ImageSource with AvaloniaUi. In WPF I was going this way:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ImageSource x:Key="Icon">path/to/image/image.png</ImageSource>
</ResourceDictionary>
And then referenced to it like this:
<Image Source="{StaticResource Icon}"/>
How can i archive the same in Avalonia?
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:imaging="clr-namespace:Avalonia.Media.Imaging;assembly=Avalonia.Visuals">
<UserControl.Resources>
<imaging:Bitmap x:Key="MyBitmap">
<x:Arguments><x:String>icon.png</x:String></x:Arguments>
</imaging:Bitmap>
</UserControl.Resources>
<Image Source="{StaticResource MyBitmap}"
Width="100" Height="200"
Stretch="None"/>
</UserControl>
Note that this only works with physical paths, since converter isn't involved anymore.
You can also try to experiment with attached properties that will accept your own image holder.

Resolving resources from one UserControl to a parent UserControl

I've got a user control UserControl1, which defines a style in its resources. That user control contains an instance of UserControl2, which references that style:
<UserControl x:Class="UserControl1">
<UserControl.Resources>
<Style x:Key="MyStyle" />
</UserControl.Resources>
<Grid>
<UserControl2 />
</Grid>
</UserControl>
<UserControl x:Class="UserControl2">
<Grid Style="{StaticResource MyStyle}">
</Grid>
</UserControl>
However, UserControl2 cannot find that style resource, even though it is in the logical tree (within the resources of UserControl1). How can I get UserControl2 to find the resources in UserControl1?
You can do it but, but I would suggest using a ResourceDictionary instead.
Anyway, if you want to do it this way you can use FindAncestor to find the parent and access the Resource you want out of the Parent ResourceDictionary
<UserControl x:Class="UserControl1">
<UserControl.Resources>
<Style x:Key="MyStyle" />
</UserControl.Resources>
<Grid>
<UserControl2 />
</Grid>
</UserControl>
<UserControl x:Class="UserControl2">
<Grid Style="{Binding Resources[MyStyle], RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:UserControl1}}}">
</Grid>
</UserControl>
Beacause Resource is a dictionary you can access using the key just like in code behind
I had the same issue and was able to solve it by referencing the resource through DynamicResource instead of StaticResource:
<UserControl x:Class="UserControl2">
<Grid Style="{DynamicResource MyStyle}">
</Grid>
</UserControl>
The compiler does still give a warning that the resource cannot be resolved.

Add converter to page resources from code behind

I would like to add a specific instance of a class to the resources of a page then use that class as a converter, so in my page constructor I put:
this.Resources.Add("converterASD", new ASDConverter());
then bind to it like this:
<ListBox ItemsSource="{Binding Converter={StaticResource converterASD}}"/>
but I keep getting this exception:
Provide value on 'System.Windows.Markup.StaticResourceHolder' threw an
exception.
I'm a bit new to WPF, any advice would be appreciated.
We could use more information from the exception.
Two suggestions:
Make sure that you add the resource before the call to InitializeComponent().
Try switching it to a dynamic resource.
You can declare the Converter you would like to use in the resource section of the page like the following example. (I recommend you declare the converter in XAML instead of the code-behind)
Example:
<UserControl x:Class="Views.ConverterExample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d" d:DesignHeight="300"
d:DesignWidth="300">
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVisibilityConverter" />
</UserControl.Resources>
<Grid>
<CheckBox x:Name="VisibilityController" IsThreeState="False" />
<ListBox
Visibility="{Binding ElementName=VisibilityController, Path=IsChecked,Converter={StaticResource BoolToVisibilityConverter}}"
Height="100" Width="100" BorderBrush="Red" BorderThickness="1" />
</Grid>
</UserControl>

Problem with static data binding in wpf

I'm relatively new to wpf and I quite don't understand binding yet.
I want to have several combo boxes in my application with the same items. The basic solution would be to copy paste but that just isn't good practice. So I thought to put a static resource with the content I want and bind all combo boxes to it. It compiles and runs well but the combo box is empty.
Here's the code:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ItemsControl x:Key="Validations">
<ItemsControl.Items>
<ComboBoxItem>String</ComboBoxItem>
<ComboBoxItem>Numeric</ComboBoxItem>
</ItemsControl.Items>
</ItemsControl>
and here's the combo box:
<ComboBox ItemsSource="{Binding Source={StaticResource Validations}}"/>
I know the solution for this is probably simple but I haven't figured it out yet. I'll keep trying ;)
Thanks
Make the resource a list of strings, not a visual element, then use the StaticResource extension to assign it to the ItemsSource property, like so:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<x:ArrayExtension x:Key="Data" Type="{x:Type sys:String}">
<sys:String>String1</sys:String>
<sys:String>String2</sys:String>
<sys:String>String3</sys:String>
</x:ArrayExtension>
</Window.Resources>
<Grid>
<StackPanel>
<ComboBox ItemsSource="{StaticResource Data}"/>
<ComboBox ItemsSource="{StaticResource Data}"/>
<ComboBox ItemsSource="{StaticResource Data}"/>
</StackPanel>
</Grid>
</Window>
Note the definition of the xmlns:sys namespace (maps to namespace System in assembly mscorlib) and the use of the x:ArrayExtension element to declare a simply array in XAML.

Resources