繁体   English   中英

在 WPF/C# 中,如何访问动态生成的控件的元素或以其他方式向它们添加单击事件?

[英]In WPF/C#, how do I access elements of dynamically generated controls or otherwise add click events to them?

我正在使用自定义控件 class 来构建具有不同细节和 OnClick 操作的外观相似的控件。 除了看起来漂亮之外,只有 function 的控件用于切换黄色按钮,因此它看起来像现代的切换按钮控件(如 Android 设置或其他)。

主要的 output 看起来像这样: 带有自定义控件的主输出

我想做的是弄清楚如何将“onclick”逻辑从控件中移出并放入主文件中,以便我可以正确地响应它。 我最初让它响应它自己在矩形和椭圆上的点击事件,如下所示:

    public partial class FixerBox : UserControl
    {
        Thickness btnDotOn = new Thickness(-60, 0, 0, 0);
        Thickness btnDotOff = new Thickness(0, 0, -60, 0);
        SolidColorBrush dotOn = new SolidColorBrush(Color.FromRgb(84, 130, 53));
        SolidColorBrush dotOff = new SolidColorBrush(Color.FromRgb(207, 178, 76));
        SolidColorBrush bkOn = new SolidColorBrush(Color.FromRgb(226, 240, 217));
        SolidColorBrush bkOff = new SolidColorBrush(Color.FromRgb(255, 242, 204));
        
        public bool IsOn { get; set; } = false;
        
        public FixerBox(Dictionary<string,string> deets)
        {
            InitializeComponent();
            btnOff();
            this.Name = deets["Name"];
            this.FixerTitle.Text = deets["Title"];
            this.FixerDesc.Text = deets["Description"];
            this.FixerTags.Text = deets["Tags"];
            this.FixerImg.Source = new BitmapImage(new Uri(deets["Img"], UriKind.Relative));
        }

        public void btnOn() 
        {
            IsOn = true;
            FixBtnBk.Fill = bkOn;
            FixBtnBk.Stroke = dotOn;
            FixBtnDot.Fill = dotOn;
            FixBtnDot.Margin = btnDotOn;
        }
        public void btnOff() 
        {
            IsOn = false;
            FixBtnBk.Fill = bkOff;
            FixBtnBk.Stroke = dotOff;
            FixBtnDot.Fill = dotOff;
            FixBtnDot.Margin = btnDotOff;
        }

        private void FixBtnBk_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            //if (isOn)
            //{
            //  btnOff();
            //}
            //else
            //{
            //  btnOn();
            //}
        }
        private void FixBtnDot_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            FixBtnBk_MouseLeftButtonDown(sender, e);
        }

    }

我现在已经注释掉了点击事件,所以我可以尝试从外部触发相同的效果:

        // The click event I'm trying to build
        private void fixClick(object sender, EventArgs e)
        {
            StatusBox.Text = "CLICK WORKS";
            FixerBox whichFix = (FixerBox)sender;
            if (whichFix.IsOn)
            {
                whichFix.btnOff();
            }
            else
            {
                whichFix.btnOn();
            }
        }

        // The constructor of my app
        public MainWindow()
        {
            InitializeComponent();
            // fixNames is a dictionary containing details of each control
            var fixNames = fixers.FixerNames();
            foreach (string key in fixNames)
            {
                var temp = fixers.GetFix(key);
                // Be sure to pass this along as well
                temp["Name"] = key;
                fixerBoxes[key] = new FixerBox(temp);
                fixerBoxes[key].FindName("FixBtnBk") = new EventHandler(fixClick);
                FixersArea.Children.Add(fixerBoxes[key]);
            }           
        }

上面是我的主要应用程序构造函数,我在其中生成所有控件。 问题是在我设置事件处理程序的那一行,我无法弄清楚如何让它真正起作用。 FindName 应该获得特定的控件,但它没有单击事件或鼠标按下或任何东西。 如何将我的自定义点击事件附加到每个控件?

我这样做的原因是因为随着切换按钮,我希望它实际进行系统更改和注册表更新以响应单击哪个控件。 我可以将所有响应保留在 class 中,并将它们包含在自定义控件中,但从系统资源的角度和编程的角度来看,这似乎很草率。

相反,如果我能弄清楚如何访问动态控件的各种元素并向它们添加单击事件(或任何等效的解决方法),那似乎更好。

如何访问动态生成的控件的元素或以其他方式向它们添加点击事件。 我想做的是弄清楚如何将“onclick”逻辑从控件中移出并放入主文件中,以便我可以正确地响应它。

正如我在上面的评论中提到的,您可以创建您可以订阅的公共事件,并根据需要响应这些事件。

在你的FixerBox class 中:

  • 添加事件: public event RoutedEventHandler MouseLeftBtnDown;

  • 在需要时调用事件:

     private void FixerBox_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { MouseLeftBtnDown?.Invoke(this, new RoutedEventArgs()); }

在您的 class 中,您想订阅这个新活动:

foreach (string key in fixNames)
            {
                var temp = fixers.GetFix(key);
                // Be sure to pass this along as well
                temp["Name"] = key;
                fixerBoxes[key] = new FixerBox(temp);
                fixerBoxes[key].MouseLeftBtnDown += fixClick;
                FixersArea.Children.Add(fixerBoxes[key]);
            }  

您的常规签名也需要更改:

 private void fixClick(object sender, RoutedEventArgs e)

这应该可以帮助您入门,如果您有任何疑问,请告诉我。

暂无
暂无

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

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