2008-10-01 21 views
8

Windows Forms允許您開發可以具有設計者的組件,非可視元素。內置組件包括BackgroundWorker,Timer和許多ADO .NET對象。這是一種提供複雜對象的簡單配置的好方法,它使設計師輔助的數據綁定成爲可能。什麼是WinForms組件的WPF等價物?

我一直在尋找WPF,它似乎沒有任何組件的概念。我對嗎?有沒有創建組件(或類似組件的東西)的一些方法,我錯過了?

我已經接受鮑勃的答案,因爲經過大量的研究,我覺得花哨的裝飾師可能是唯一的方法來做到這一點。

回答

5

僅僅從我自己的觀察,似乎微軟正試圖擺脫組件和類似的東西在GUI中。我認爲WPF試圖限制XAML中的大部分內容,以便嚴格控制GUI。數據綁定我想是唯一的例外。我知道我試圖將大部分其他代碼保留在代碼隱藏或獨立的類或程序集中。

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

1

到目前爲止,我認爲唯一有意義的方法是將該類的實例設置爲靜態資源並從XAML進行配置。這很有效,但如果有像WinForms設計器組件托盤這樣的東西,它會很好。

1

你可以在資源字典中放入任何你喜歡的東西,包括那些與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> 
1

我有同樣的問題。類似組件的機制的優點是設計人員可以將其添加到Blend中,使用Properties編輯器在設計器中對其進行配置,並使用數據綁定。您如何看待下面的解決方案?有用。

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> 
相關問題