2008-10-01 6 views
8

Windows Forms le permite desarrollar Componentes, elementos no visuales que pueden tener un diseñador. Los componentes incorporados incluyen BackgroundWorker, Timer y muchos objetos ADO .NET. Es una forma agradable de proporcionar una configuración sencilla de un objeto complicado, y permite el enlace de datos asistido por el diseñador.¿Cuál es el equivalente de WPF de los componentes de WinForms?

He estado buscando en WPF, y no parece que haya ningún concepto de componentes. ¿Estoy en lo cierto acerca de esto? ¿Hay algún método para crear componentes (o algo así como un componente) que me he perdido?

He aceptado la respuesta de Bob porque después de mucha investigación siento que Adorners de lujo son probablemente la única forma de hacerlo.

Respuesta

5

Solo por mis propias observaciones, parece que Microsoft está tratando de alejarse de tener componentes y cosas similares en la GUI. Creo que WPF intenta limitar la mayoría de lo que está en el XAML estrictamente a las cosas de GUI. El enlace de datos supongo que sería la única excepción. Sé que trato de mantener casi todo lo demás en el código subyacente o en clases o conjuntos separados.

Probablemente no sea exactamente la respuesta que quería, pero es mi $ 0.02.

1

Hasta ahora, el único enfoque que veo que tiene sentido es convertir una instancia de la clase en un recurso estático y configurarlo desde XAML. Esto funciona, pero estaría bien si hubiera algo como la bandeja de componentes de diseño de WinForms en la que podrían vivir.

1

Puede poner lo que quiera dentro de un diccionario de recursos, incluidas las clases que no tienen relación alguna con Wpf.

El siguiente XAML agrega la cadena "Hola" directamente en una ventana (la cadena real, no un control que muestra la cadena), puede usar el mismo método para colocar cualquier cosa, incluidas las clases que escribe en un archivo 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

Tengo la misma pregunta. La ventaja de un mecanismo similar a un componente es que el diseñador puede agregarlo en Blend, configurarlo en el diseñador con el editor de Propiedades y usar el enlace de datos. ¿Qué piensas de la solución a continuación? Funciona.

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 
} 

Y se utiliza de la siguiente manera.

<StackPanel> 
    <lib:TimerComponent Period="{Binding ElementName=textBox1, Path=Text}" Tick="OnTimerTick" /> 
    <TextBox x:Name="textBox1" Text="1000" /> 
    <Label x:Name="label1" /> 
</StackPanel> 
Cuestiones relacionadas