从 UWP 中的 IconElement 或 IconSourceElement 派生

Kan*_*n P 5 c# uwp uwp-xaml winui winui-3

我正在尝试创建与 MS SymbolIcon 相同的自定义符号图标控件,它将获取枚举符号值作为输入,并且将从字典<Symbol, string> 集合中检索等效路径数据值。但是从 IconElement 继承的符号图标类以及我的应用程序中面临的以下相同问题。

“IconElement 不采用带有 0 个参数的构造函数”

从 UWP 中的 IconElement 派生

但我已将我的构造函数标记为 extern 并用分号括起来以解决构造函数问题。

public class CustomSymbolIcon : IconElement
{ 
   public extern CustomSymbolIcon(); 
}
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)
  1. How to initialize dictionary in constructor of custom class? - Need to populate the dictionary when control loaded. I can't call this method in extern constructor.
  2. If possible, path geometry retrieval using symbol achieved by Dictionary<Symbol, String> collection populated. Is this efficient way?,Bcz it leads to key already added in collection issue when initialize the control at second time. Please suggest alternate ways to achieve this.
  3. How can write style for framework element? I need to bind the Path data in control style. But it doesn't have template property.

Can anyone suggest how to achieve this?

Nic*_*SFT 1

派生自 UWP 中的 IconElement 或 IconSourceElement

恐怕您无法CustomSymbolIcon继承IconElement,并且IconElement没有提供设置方法ControlTemplate,对于您的场景,我们建议您使用自定义Datatemplate来替换,NavigationViewItem如下所示

<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>
Run Code Online (Sandbox Code Playgroud)