什么是WinForms组件的WPF等效项?
时间:2020-03-06 14:58:39 来源:igfitidea点击:
Windows窗体使我们可以开发组件,可以具有设计器的非可视元素。内置组件包括BackgroundWorker,Timer和许多ADO .NET对象。这是提供简单配置复杂对象的好方法,并且它启用了设计人员辅助的数据绑定。
我一直在研究WPF,似乎没有任何组件概念。我说得对吗?是否有一些我错过的创建组件(或者类似组件的东西)的方法?
我接受了鲍勃的回答,因为经过大量研究,我觉得花哨的装饰师可能是唯一的方法。
解决方案
到目前为止,我认为唯一有意义的方法是使该类的实例成为静态资源,并从XAML对其进行配置。这行得通,但如果可以将WinForms Designer组件托盘之类的东西放进去,那将是一个很好的选择。
仅根据我自己的观察,似乎Microsoft试图摆脱在GUI中具有组件和类似内容的趋势。我认为WPF试图将XAML中的大部分内容限制为严格的GUI。我想数据绑定是唯一的例外。我知道我会尽力将大多数其他内容保留在代码中,或者保留在单独的类或者程序集中。
可能不完全是我们想要的答案,但这是我的0.02美元。
我们可以将任何我们喜欢的东西放到资源字典中,包括与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>
我也有同样的问题。类似于组件的机制的优点是,设计人员可以将其添加到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>