Windows 窗体允许您开发组件,非可视元素,可以有一个设计器。内置组件包括 BackgroundWorker、Timer 和许多 ADO .NET 对象。这是一种为复杂对象提供简单配置的好方法,它支持设计人员辅助的数据绑定。
我一直在看WPF,似乎没有任何组件的概念。我是对的吗?是否有一些我错过的创建组件(或类似组件)的方法?
我接受了 Bob 的回答,因为经过大量研究后,我觉得花哨的 Adorners 可能是做到这一点的唯一方法。
Windows 窗体允许您开发组件,非可视元素,可以有一个设计器。内置组件包括 BackgroundWorker、Timer 和许多 ADO .NET 对象。这是一种为复杂对象提供简单配置的好方法,它支持设计人员辅助的数据绑定。
我一直在看WPF,似乎没有任何组件的概念。我是对的吗?是否有一些我错过的创建组件(或类似组件)的方法?
我接受了 Bob 的回答,因为经过大量研究后,我觉得花哨的 Adorners 可能是做到这一点的唯一方法。
仅从我自己的观察来看,微软似乎正试图摆脱在 GUI 中使用组件和类似的东西。我认为 WPF 试图将 XAML 中的大部分内容限制为严格的 GUI 内容。我猜数据绑定将是唯一的例外。我知道我尝试将其他大部分内容保留在代码隐藏或单独的类或程序集中。
可能不是您想要的答案,但这是我的 0.02 美元。
我也有同样的问题。类组件机制的优点是设计者可以将其添加到 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>