2008-10-01 2 views
8

Windows Forms позволяет разрабатывать компоненты, невизуальные элементы, которые могут иметь конструктор. В состав встроенных компонентов входят BackgroundWorker, Timer и множество объектов ADO .NET. Это хороший способ обеспечить легкую настройку сложного объекта, и он позволяет привязку данных с помощью конструктора.Что такое WPF-эквивалент компонентов WinForms?

Я смотрел на WPF, и, похоже, нет какой-либо концепции компонентов. Правильно ли я об этом? Есть ли способ создания компонентов (или что-то вроде компонента), которые я пропустил?

Я принял ответ Боба, потому что после многих исследований я чувствую, что причудливые Адренеры, вероятно, единственный способ сделать это.

ответ

5

Как мне кажется, Microsoft пытается отойти от компонентов и подобных вещей в графическом интерфейсе. Я думаю, 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, настроить его в конструкторе с помощью редактора свойств и использовать привязку данных. Что вы думаете о решении ниже? Оно работает.

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>