【问题标题】:What's the WPF equivalent of WinForms components?WinForms 组件的 WPF 等效项是什么?
【发布时间】:2010-09-14 12:59:22
【问题描述】:

Windows 窗体允许您开发组件,非可视元素可以有一个设计器。内置组件包括 BackgroundWorker、Timer 和许多 ADO .NET 对象。这是一种为复杂对象提供简单配置的好方法,它支持设计人员辅助的数据绑定。

我一直在研究 WPF,它似乎没有任何组件的概念。我是对的吗?是否有一些我错过的创建组件(或类似组件)的方法?

我接受了 Bob 的回答,因为经过大量研究后,我觉得花哨的 Adorners 可能是做到这一点的唯一方法。

【问题讨论】:

  • winforms 中的组件还可以为工具提示或验证等控件添加新功能。

标签: wpf winforms components


【解决方案1】:

到目前为止,我认为唯一有意义的方法是将类的实例设为静态资源并从 XAML 配置它。这行得通,但如果有类似 WinForms 设计器组件托盘之类的东西可以容纳这些东西,那就太好了。

【讨论】:

    【解决方案2】:

    根据我自己的观察,微软似乎正试图摆脱在 GUI 中使用组件和类似的东西。我认为 WPF 试图将 XAML 中的大部分内容限制为严格的 GUI 内容。我猜数据绑定将是唯一的例外。我知道我尝试将其他大部分内容保留在代码隐藏或单独的类或程序集中。

    可能不是您想要的答案,但这是我的 0.02 美元。

    【讨论】:

      【解决方案3】:

      您可以将任何您喜欢的内容放入资源字典中,包括与 Wpf 没有任何关系的类。

      以下 XAML 将字符串“Hello”直接添加到窗口中(实际字符串,而不是显示字符串的控件),您可以使用相同的方法放置任何内容 - 包括您自己编写的类到 XAML 文件中。

      <Window  x:Class="MyApp.Window1"
          xmlns:sys="clr-namespace:System;assembly=mscorlib"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          >
      <Window.Resources>
          <sys:String x:Key="MyString">Hello</sys:String>
      </Window.Resources>
      </Window>
      

      【讨论】:

        【解决方案4】:

        我也有同样的问题。类组件机制的优点是设计者可以在 Blend 中添加它,在设计器中使用属性编辑器对其进行配置,并使用数据绑定。您如何看待下面的解决方案?它有效。

        public class TimerComponent : FrameworkElement
        {
            public Timer Timer { get; protected set; }
        
            public TimerComponent()
            {
                if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
                {
                    Visibility = Visibility.Collapsed;
                    Timer = new Timer(OnTimerTick, null, Timeout.Infinite, Timeout.Infinite);
                }
            }
        
            void OnTimerTick(object ignore)
            {
                Dispatcher.BeginInvoke(new Action(RaiseTickEvent));
            }
        
            #region DueTime Dependency Property
        
            public int DueTime
            {
                get { return (int)GetValue(DueTimeProperty); }
                set { SetValue(DueTimeProperty, value); }
            }
        
            public static readonly DependencyProperty DueTimeProperty =
                DependencyProperty.Register("DueTime", typeof(int), typeof(TimerComponent), new UIPropertyMetadata(new PropertyChangedCallback(OnDueTimeChanged)));
        
            static void OnDueTimeChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
            {
                var target = obj as TimerComponent;
                if (target.Timer != null)
                {
                    var newDueTime = (int)e.NewValue;
                    target.Timer.Change(newDueTime, target.Period);
                }
            }
        
            #endregion
        
            #region Period Dependency Property
        
            public int Period
            {
                get { return (int)GetValue(PeriodProperty); }
                set { SetValue(PeriodProperty, value); }
            }
        
            public static readonly DependencyProperty PeriodProperty =
                DependencyProperty.Register("Period", typeof(int), typeof(TimerComponent), new UIPropertyMetadata(new PropertyChangedCallback(OnPeriodChanged)));
        
            static void OnPeriodChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
            {
                var target = obj as TimerComponent;
                if (target.Timer != null)
                {
                    var newPeriod = (int)e.NewValue;
                    target.Timer.Change(target.DueTime, newPeriod);
                }
            }
        
            #endregion
        
            #region Tick Routed Event
        
            public static readonly RoutedEvent TickEvent = EventManager.RegisterRoutedEvent(
                "Tick", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TimerComponent));
        
            public event RoutedEventHandler Tick
            {
                add { AddHandler(TickEvent, value); }
                remove { RemoveHandler(TickEvent, value); }
            }
        
            private void RaiseTickEvent()
            {
                RoutedEventArgs newEventArgs = new RoutedEventArgs(TimerComponent.TickEvent);
                RaiseEvent(newEventArgs);
            }
        
            #endregion
        }
        

        并且如下使用。

        <StackPanel>
            <lib:TimerComponent Period="{Binding ElementName=textBox1, Path=Text}" Tick="OnTimerTick" />
            <TextBox x:Name="textBox1" Text="1000" />
            <Label x:Name="label1" />
        </StackPanel>
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-10-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-03-11
          相关资源
          最近更新 更多