简体   繁体   English

WinUI 3 中的 UserControl:如何设置图像的“来源”属性和按钮的“点击”事件?

[英]UserControl in WinUI 3: how to set the 'source' property of an image and the 'click' event of a button?

I'm building a UserControl that should display a button with an image and text.我正在构建一个应该显示带有图像和文本的按钮的 UserControl。 I access that UserControl in the App like this:我像这样在应用程序中访问该 UserControl:

<local:ButtonWithImage
ButtonClick="Button1_Click"
ButtonImage="Assets/Clipboard 4.png"
ButtonText="Clipboard History"
ButtonWidth="200" />

Out of the 4 properties displayed in the code above, two of them are working fine, which are ButtonText and ButtonWidth.在上面代码中显示的 4 个属性中,有两个工作正常,它们是 ButtonText 和 ButtonWidth。 But the ButtonClick and ButtonImage properties are causing errors, which I'll explain next.但是 ButtonClick 和 ButtonImage 属性导致错误,我将在接下来解释。

The UserControl code is this:用户控件代码是这样的:

xaml: xaml:

<UserControl
    x:Class="Launcher_WinUI3_Net_6.ButtonWithImage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="using:Launcher_WinUI3_Net_6"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <StackPanel>
        <StackPanel Orientation="Horizontal">
            <Button x:Name="button">
                <StackPanel Orientation="Horizontal">
                    <Image x:Name="image"/>
                    <TextBlock x:Name="textBlock" />
                </StackPanel>
            </Button>
        </StackPanel>
        <TextBlock Height="1" />
    </StackPanel>
</UserControl>

C#: C#:

public sealed partial class ButtonWithImage : UserControl
    {
        public ButtonWithImage()
        {
            this.InitializeComponent();
        }

        public string ButtonText
        {
            get { return (string)GetValue(ButtonTextProperty); }
            set { SetValue(ButtonTextProperty, value); }
        }

        public static readonly DependencyProperty
        ButtonTextProperty = 
        DependencyProperty.Register("ButtonText",
        typeof(string), typeof(ButtonWithImage), 
        new PropertyMetadata(string.Empty, ButtonTextValue));

        private static void ButtonTextValue(DependencyObject d,
        DependencyPropertyChangedEventArgs e)
        {
            var buttonWithImage = d as ButtonWithImage;
            var buttonWithImageProperty = buttonWithImage.FindName("textBlock") as TextBlock;
            buttonWithImageProperty.Text = e.NewValue.ToString();
        }




        public string ButtonWidth
        {
            get { return (string)GetValue(ButtonWidthProperty); }
            set { SetValue(ButtonWidthProperty, value); }
        }

        public static readonly DependencyProperty
        ButtonWidthProperty =
        DependencyProperty.Register("ButtonWidth",
        typeof(string), typeof(ButtonWithImage), 
        new PropertyMetadata(string.Empty, ButtonWidthValue));

        private static void ButtonWidthValue(DependencyObject d,
        DependencyPropertyChangedEventArgs e)
        {
            var buttonWithImage = d as ButtonWithImage;
            var buttonWithImageProperty = buttonWithImage.FindName("button") as Button;
            buttonWithImageProperty.Width = Convert.ToDouble(e.NewValue.ToString());
        }




        public string ButtonClick
        {
            get { return (string)GetValue(ButtonClickProperty); }
            set { SetValue(ButtonClickProperty, value); }
        }

        public static readonly DependencyProperty
        ButtonClickProperty =
        DependencyProperty.Register("ButtonClick",
        typeof(string), typeof(ButtonWithImage),
        new PropertyMetadata(string.Empty, ButtonClickValue));

        private static void ButtonClickValue(DependencyObject d,
        DependencyPropertyChangedEventArgs e)
        {
            var buttonWithImage = d as ButtonWithImage;
            var buttonWithImageProperty = buttonWithImage.FindName("button") as Button;
            buttonWithImageProperty.Click += e.NewValue.ToString();
        }







        public string ButtonImage
        {
            get { return (string)GetValue(ButtonImageProperty); }
            set { SetValue(ButtonImageProperty, value); }
        }

        public static readonly DependencyProperty
        ButtonImageProperty =
        DependencyProperty.Register("ButtonImage",
        typeof(string), typeof(ButtonWithImage),
        new PropertyMetadata(string.Empty, ButtonImageValue));

        private static void ButtonImageValue(DependencyObject d,
        DependencyPropertyChangedEventArgs e)
        {
            var buttonWithImage = d as ButtonWithImage;
            var buttonWithImageProperty = buttonWithImage.FindName("image") as Image;
            buttonWithImageProperty.Source = e.NewValue.ToString();
        }





    }

The code for the ButtonClick is generating this error: Cannot implicitly convert type 'string' to 'Microsoft.UI.Xaml.RoutedEventHandler' ButtonClick的代码生成此错误:无法将类型“字符串”隐式转换为“Microsoft.UI.Xaml.RoutedEventHandler”

And the code for the ButtonImage is generating this error: Cannot implicitly convert type 'string' to 'Microsoft.UI.Xaml.Media.ImageSource' ButtonImage的代码生成此错误:无法将类型“字符串”隐式转换为“Microsoft.UI.Xaml.Media.ImageSource”

I don't have much experience with creating UserControls so I'm following some examples I've seen on the inte.net, but none of them address these two problems I'm facing.我在创建用户控件方面没有太多经验,所以我按照我在 inte.net 上看到的一些示例进行操作,但它们都没有解决我面临的这两个问题。

======================================================== ================================================ ======

Update 1 based on answer from Andrew KeepCoding:根据 Andrew KeepCoding 的回答更新 1:

Thanks Andrew:!!谢谢安德鲁:!! There is still an error going on: No overload for 'Button52_Click' matches delegate 'EventHandler'仍然存在错误: “Button52_Click”没有重载匹配委托“EventHandler”

UserControl in the App:应用程序中的用户控件:

<local:ButtonWithImage
ButtonImage="Assets/Clipboard 4.png"
ButtonText="Clipboard History"
ButtonWidth="200"
Click="Button52_Click" />

Button52_Click signature: Button52_Click 签名:

private void Button52_Click(object sender, RoutedEventArgs e)
{
    foo();
}

UserControl 'Click' event signature:用户控件“单击”事件签名:

public event EventHandler? Click;
private void button_Click(object sender, RoutedEventArgs e) 
{
    Click?.Invoke(this, EventArgs.Empty);
}

The signatures are the same, even so the error No overload for 'Button52_Click' matches delegate 'EventHandler' is occurring The error is occurring here, in 'case 41:':签名是相同的,即便如此错误No overload for 'Button52_Click' matches delegate 'EventHandler' is occurring The error is occurring here, in 'case 41:':

case 40: // MainWindow.xaml line 1288
{
  global::Microsoft.UI.Xaml.Controls.Button element40 = global::WinRT.CastExtensions.As<global::Microsoft.UI.Xaml.Controls.Button>(target);
  ((global::Microsoft.UI.Xaml.Controls.Button)element40).Click += this.Button51_Click;
}
break;

case 41: // MainWindow.xaml line 1199
{
  global::Launcher_WinUI3_Net_6.ButtonWithImage element41 = global::WinRT.CastExtensions.As<global::Launcher_WinUI3_Net_6.ButtonWithImage>(target);
  ((global::Launcher_WinUI3_Net_6.ButtonWithImage)element41).Click += this.Button52_Click;
}
break;

======================================================== ================================================ ======

Update 2: The Button52_Click signature should be:更新 2:Button52_Click 签名应该是:

private void Button52_Click(object sender, EventArgs e)
{
    foo();
}

And not:并不是:

private void Button52_Click(object sender, RoutedEventArgs e)
{
    foo();
}

Instead of typeof(string) , you should use the actual type for your dependency properties.您应该为依赖属性使用实际类型,而不是typeof(string)

For example, I'm using ImageSource for the ButtonImage in the code below:例如,我在下面的代码中使用ImageSource作为ButtonImage

<UserControl
    x:Class="UserControls.ButtonWithImage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <StackPanel>
        <StackPanel Orientation="Horizontal">
            <Button
                x:Name="button"
                Click="button_Click">
                <StackPanel Orientation="Horizontal">
                    <Image
                        x:Name="image"
                        Source="{x:Bind ButtonImage, Mode=OneWay}" />
                    <TextBlock
                        x:Name="textBlock"
                        Text="{x:Bind ButtonText, Mode=OneWay}" />
                </StackPanel>
            </Button>
        </StackPanel>
        <TextBlock Height="1" />
    </StackPanel>
</UserControl>
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media;
using System;

namespace UserControls;

public sealed partial class ButtonWithImage : UserControl
{
    public static readonly DependencyProperty ButtonTextProperty = DependencyProperty.Register(
        nameof(ButtonText),
        typeof(string),
        typeof(ButtonWithImage),
        new PropertyMetadata(default));

    public static readonly DependencyProperty ButtonImageProperty = DependencyProperty.Register(
        nameof(ButtonImage),
        typeof(ImageSource),
        typeof(ButtonWithImage),
        new PropertyMetadata(default));

    public ButtonWithImage()
    {
        this.InitializeComponent();
    }

    public event EventHandler? Click;

    public string ButtonText
    {
        get => (string)GetValue(ButtonTextProperty);
        set => SetValue(ButtonTextProperty, value);
    }

    public ImageSource? ButtonImage
    {
        get => (ImageSource?)GetValue(ButtonImageProperty);
        set => SetValue(ButtonImageProperty, value);
    }

    private void button_Click(object sender, RoutedEventArgs e)
    {
        Click?.Invoke(this, EventArgs.Empty);
    }
}

And use it like this:并像这样使用它:

<local:ButtonWithImage
    ButtonText="Text"
    ButtonImage="Assets/StoreLogo.png"
    Click="ButtonWithImage_Click" />
private void ButtonWithImage_Click(object sender, EventArgs e)
{
}

You should also consider a custom control derived from a Button.您还应该考虑派生自 Button 的自定义控件。 These videos might help.这些视频可能会有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM