I'm trying to create the same custom symbol icon control as MS SymbolIcon, which will get the enum symbol values as input, and the equivalent path data value will be retrieved from the dictionary<Symbol, string> collection. But the symbol icon class inherited from IconElement and the same below issue faced in my application.
'IconElement does not take a constructor that takes 0 arguments'
Derive from IconElement in UWP
but I have marked my constructor as extern and enclosed with semicolon to resolve the constructor issue.
public class CustomSymbolIcon : IconElement
{
public extern CustomSymbolIcon();
}
But my question is, I can get input from the end user as Symbol Enum and retrieved equivalent path geometry based on input from the stored dictionary. But I couldn't bind the path geometry to the path element(Targeted Custom icon class)and I can't write the template style for this class. Because IconElement was derived from the framework element.
I can achieve these all with control class , but I can't use this inside the <NavigationView.Icon> (its a IconElement base) tag due to base class.
public class SymbolToIconConversion : Control //IconElement instead of control
{
internal static Dictionary<Symbol, string> enumValuesCollection = new Dictionary<Symbol, string>();
public SymbolToIconConversion()
{
this.DefaultStyleKey = typeof(SymbolToIconConversion);
PopulateEnumCollection();
}
public static Dictionary<Symbol, string> EnumValuesCollection
{
get { return enumValuesCollection; }
set { enumValuesCollection = value; }
}
internal void PopulateEnumCollection()
{
enumValuesCollection.Add(Symbol.Accept, "M0,4 5,9 9,0 4,5");
enumValuesCollection.Add(Symbol.Close, "F1 M 22,12L 26,12L 26,22L 36,22L 36,26L 26,26L 26,36L 22,36L 22,26L 12,26L 12,22L 22,22L 22,12 Z");
enumValuesCollection.Add(Symbol.Save, "M0,4 5,9 9,0 4,5");
enumValuesCollection.Add(Symbol.Add, "M0,5 H10 M5,5 V10Z");
}
public Symbol Symbol
{
get { return (Symbol)GetValue(SymbolProperty); }
set { SetValue(SymbolProperty, value); }
}
// Using a DependencyProperty as the backing store for Symbol. This enables animation, styling, binding, etc...
public static readonly DependencyProperty SymbolProperty =
DependencyProperty.Register("Symbol", typeof(Symbol), typeof(SfSymbolIcon), new PropertyMetadata(typeof(Symbol), new PropertyChangedCallback(OnSymbolChanged)));
internal Geometry Geometry
{
get { return (Geometry)GetValue(GeometryProperty); }
set { SetValue(GeometryProperty, value); }
}
// Using a DependencyProperty as the backing store for Geometry. This enables animation, styling, binding, etc...
internal static readonly DependencyProperty GeometryProperty =
DependencyProperty.Register("Geometry", typeof(Geometry), typeof(SymbolToIconConversion), new PropertyMetadata(null));
private static void OnSymbolChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
SymbolToIconConversion symbolIcon = d as SymbolToIconConversion;
if (symbolIcon != null)
{
foreach (var value in EnumValuesCollection)
{
if (symbolIcon.Symbol == value.Key)
{
symbolIcon.Geometry = (Geometry)XamlBindingHelper.ConvertValue(typeof(Geometry), value.Value);
return;
}
}
}
}
<Style TargetType="core:SymbolToIconConversion">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="core:SymbolToIconConversion">
<Viewbox x:Name="ContentViewbox" AutomationProperties.AccessibilityView="Raw" HorizontalAlignment="Stretch" Height="{ThemeResource AppBarButtonContentHeight}" Margin="{ThemeResource AppBarButtonContentViewboxCollapsedMargin}">
<Path x:Name="Content"
Width="{Binding Width, RelativeSource={RelativeSource Mode=TemplatedParent}}"
Height="{Binding Height, RelativeSource={RelativeSource Mode=TemplatedParent}}"
Fill="{Binding Foreground, RelativeSource={RelativeSource Mode=TemplatedParent}}"
Data="{Binding Geometry, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
</Viewbox>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Can anyone suggest how to achieve this?
Derive from IconElement or IconSourceElement in UWP
I'm afraid you can't make CustomSymbolIcon
that inherit IconElement
, and IconElement
does not provide method to set ControlTemplate
, for your scenario, we suggest you use custom Datatemplate
to replace NavigationViewItem
like the following
<NavigationView.MenuItemTemplate>
<DataTemplate>
<Grid Width="{Binding ElementName=nvSample, Path=OpenPaneLength}" HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<local:SymbolToIconConversion Symbol="Accept" VerticalAlignment="Center"/>
<StackPanel
Grid.Column="1"
Margin="45,0,10,0"
HorizontalAlignment="Stretch"
VerticalAlignment="Center">
<TextBlock x:Name="Header" Text="Header" />
<TextBlock x:Name="Line1" Text="TheFirstLine" />
</StackPanel>
</Grid>
</DataTemplate>
</NavigationView.MenuItemTemplate>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With