2008-10-01 34 views
8

Windows Forms cho phép bạn phát triển các thành phần, thành phần không trực quan có thể có một nhà thiết kế. Các thành phần tích hợp bao gồm BackgroundWorker, Timer và rất nhiều đối tượng ADO .NET. Đó là một cách hay để cung cấp cấu hình dễ dàng của một đối tượng phức tạp và nó cho phép ràng buộc dữ liệu được thiết kế riêng.Tương đương WPF của các thành phần WinForms là gì?

Tôi đã xem WPF và dường như không có khái niệm về thành phần nào. Tôi có đúng về điều này không? Có một số phương pháp tạo các thành phần (hoặc một cái gì đó giống như một thành phần) mà tôi đã bỏ qua?

Tôi đã chấp nhận câu trả lời của Bob vì sau rất nhiều nghiên cứu, tôi cảm thấy như Adorners ưa thích có lẽ là cách duy nhất để làm điều này.

Trả lời

5

Chỉ từ quan sát của riêng tôi, có vẻ như Microsoft đang cố gắng di chuyển ra khỏi việc có các thành phần và những thứ tương tự trong GUI. Tôi nghĩ rằng WPF cố gắng để hạn chế hầu hết những gì trong XAML để đúng GUI những điều. Ràng buộc dữ liệu tôi đoán sẽ là ngoại lệ duy nhất. Tôi biết tôi cố gắng giữ hầu hết mọi thứ khác trong đoạn mã phía sau hoặc trong các lớp học hoặc hội đồng riêng biệt.

Có thể không chính xác câu trả lời bạn muốn, nhưng đó là $ 0,02 của tôi.

1

Cho đến nay, cách tiếp cận duy nhất tôi thấy có ý nghĩa là tạo một thể hiện của lớp là tài nguyên tĩnh và định cấu hình nó từ XAML. Điều này làm việc, nhưng nó sẽ được tốt đẹp nếu có một cái gì đó giống như khay thành phần thiết kế WinForms mà có thể sống.

1

Bạn có thể đặt bất kỳ thứ gì bạn thích trong từ điển tài nguyên, bao gồm các lớp không có quan hệ gì với Wpf.

XAML sau thêm chuỗi "Hello" trực tiếp vào cửa sổ (chuỗi thực, không phải là điều khiển hiển thị chuỗi), bạn có thể sử dụng cùng phương pháp để đặt bất kỳ thứ gì - bao gồm các lớp bạn tự viết vào tệp 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

Tôi có cùng một câu hỏi. Lợi thế của một cơ chế giống như thành phần là nhà thiết kế có thể thêm nó vào trong Blend, cấu hình nó trong trình thiết kế với trình soạn thảo Properties và sử dụng ràng buộc dữ liệu. Bạn nghĩ gì về giải pháp dưới đây? Nó hoạt động.

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 
} 

Và được sử dụng như sau.

<StackPanel> 
    <lib:TimerComponent Period="{Binding ElementName=textBox1, Path=Text}" Tick="OnTimerTick" /> 
    <TextBox x:Name="textBox1" Text="1000" /> 
    <Label x:Name="label1" /> 
</StackPanel> 
Các vấn đề liên quan