Windows Forms允许开发组件,这些组件是非可视元素,可以拥有设计器。内置组件包括BackgroundWorker、Timer和许多ADO .NET对象。这是一种提供复杂对象易于配置的好方法,并且它可以启用设计器辅助数据绑定。
我一直在研究WPF,似乎没有任何组件的概念。我对此正确吗?是否有创建组件(或类似组件的东西)的方法我错过了?
我接受了Bob的答案,因为经过大量研究,我觉得花哨的Adorners可能是唯一的方法。
Windows Forms允许开发组件,这些组件是非可视元素,可以拥有设计器。内置组件包括BackgroundWorker、Timer和许多ADO .NET对象。这是一种提供复杂对象易于配置的好方法,并且它可以启用设计器辅助数据绑定。
我一直在研究WPF,似乎没有任何组件的概念。我对此正确吗?是否有创建组件(或类似组件的东西)的方法我错过了?
我接受了Bob的答案,因为经过大量研究,我觉得花哨的Adorners可能是唯一的方法。
仅从我的观察来看,微软似乎正在尝试摆脱在GUI中拥有组件和类似的东西。我认为WPF试图将大部分XAML中的内容限制在严格的GUI事物上。数据绑定可能是唯一的例外。我知道我尝试将大多数其他内容保留在代码后台或单独的类或程序集中。
也许不完全是你想要的答案,但这是我的2美分。
我有同样的问题。组件化机制的优点是设计师可以在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>
到目前为止,我唯一看到有意义的方法是将类的一个实例作为静态资源,并从XAML中进行配置。这样做是有效的,但如果有类似WinForms设计器组件托盘的东西来容纳这些内容,那就更好了。
你可以在资源字典中放置任何你喜欢的东西,包括与 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>