ModernWpf
ModernWpf copied to clipboard
Cannot set AppBarButton Icon from Style
Hi @Kinnara,
thank you for all your work on this great library!
I tried to define a Style
for an AppBarButton
that speciffes the AppBarButton.Icon
property.
Apparently, the Style only works on a single instance of the button.
If multiple buttons apply the same style, then only the last button will display the icon.
The Icon
property is of type IconElement
: FrameworkElement
.
AFAIK, an element can only be used once in the visual tree.
I haven't been able to find a workaround for this current limitation.
Usually, control properties are either Freezable
or a pair of { Content, ContentTemplate }, to allow templating.
Maybe the new IconSource
provides an elegant solution to this problem?
But the AppBarButton (both UWP XAML and WinUI 3.0) don't support the IconSource classes yet. It would be better to open a feature request on the WinUI repo. We should also let them know.
One way to solve this would be to make a custom markup extension. (a temporary workaround. Not elegant but will do the job)
If you can't make a custom markup extension that will return an IconElement
instance, then let me know.
I could provide you some code samples.
@wmrutten,
As for the workaround, the Windows-Community-Toolkit provides the markup extensions for IconElements. The same extensions are also provided in the ModernWpf-Community-Toolkit. You can readily use the toolkit with a ModernWpf application.
You can either include just these files in your code https://github.com/ModernWpf-Community/ModernWpfCommunityToolkit/tree/master/ModernWpf.Toolkit.UI/Extensions/Markup (BitmapIconExtension, FontIconExtension and SymbolIconExtension are enough for your case) or reference the ModernWpf.Toolkit.UI nuget package and use it instead.
This MS Doc demonstrates how to use the markup extensions https://docs.microsoft.com/en-us/windows/communitytoolkit/extensions/iconmarkupextensions
The toolkit still lacks a markup extension for PathIcon though. Are these enough for you? (for now?)
Hi @ShankarBUS,
thank you for your feedback!
i am using a markup extension. But when assigning AppBarButton.Icon from a Style, the markup extension is evaluated only once (when parsing the style). The resulting IconElement is then (illegally) re-used for all instances that apply the style. However each element should receive it's own IconElement instance. Not sure how to work around this - if it is even possible? I think this is why a Control should not expose properties of type FrameworkElement
, but instead allow the consumer to assign a template.
For now, I simply stopped using Styles (for AppBarButton
).
Oh! Sorry I misread your statement 😅.
I didn't notice you were referring to a style. Yeah in that case a markup extension won't work.
OK, thank you for confirming my suspicion.
Then I guess this is actually an issue of the original UWP AppBarButton
control.
Unless the WPF behavior is different from UWP?
This is actually possible in WPF, thanks to the x:Shared attribute:
<ui:SymbolIcon x:Key="SaveIcon" Symbol="Save" x:Shared="False" />
<Style x:Key="SaveButtonStyle" TargetType="ui:AppBarButton">
<Setter Property="Icon" Value="{StaticResource SaveIcon}" />
<Setter Property="Label" Value="Save" />
</Style>
<ui:CommandBar>
<ui:AppBarButton Style="{StaticResource SaveButtonStyle}" />
<ui:AppBarButton Style="{StaticResource SaveButtonStyle}" />
<ui:AppBarButton Style="{StaticResource SaveButtonStyle}" />
</ui:CommandBar>
@Kinnara, 👏👏👏 That's it, problem solved!
Hi @Kinnara , thank you for your feedback.
Indeed, the issue is related to resource sharing. I am aware of the x:Shared
attribute, it fixes the problem for global resources declared in XAML.
In this case, I was trying to provide the icon resource in a Style through a (custom) markup extension that returns a (custom) FontIcon
, programmatically. The markup extension would need to return a separate FontIcon instance for each target control that the style is applied to, similar to x:Shared
behavior. Maybe this is possible by hooking the target control from the markup extension, but I didn't explore any further.
Nonetheless, I understand the motivations for this library to stay close to the original UWP interface and I'm perfectly happy w/o support for AppBarButton
styling.
Thanks for all you hard work, guys. This library provides great UI improvements that are happily received by our app users. Quite amazing to see WinUI design running on an old Windows 7 (!) machine.
Kudos and keep it up!