2009-07-17 19 views
8

Hice un UserControl que debe actualizarse una vez cada pocos segundos con datos de un puerto serie. Este UserControl debe ser muy simple, que consiste en una etiqueta para un nombre de campo y otra etiqueta que contiene el valor del campo. Yo digo que debería ser simple, pero no funciona. No se actualiza en absoluto, y ni siquiera muestra el nombre del campo.wpf problema al usar propiedades de dependencia en un UserControl

A continuación se muestra el código:

public partial class LabeledField : UserControl { 

    public LabeledField() { 
     InitializeComponent(); 
    } 

    public string fieldName { 
     get { return fieldNameLabel.Content.ToString(); } 
     set { fieldNameLabel.Content = value; } 
    } 

    public string fieldValue { 
     get { return (string)GetValue(fieldValueProperty); } 
     set { SetValue(fieldValueProperty, value); } 
    } 

    public static readonly DependencyProperty fieldValueProperty = 
     DependencyProperty.Register(
      "fieldValue", 
      typeof(string), 
      typeof(LabeledField), 
      new FrameworkPropertyMetadata(
       "No Data" 
      ) 
     ) 
    ; 
} 

Aquí es el XAML:

<UserControl x:Class="DAS1.LabeledField" Name="LF" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 
<StackPanel Orientation="Horizontal"> 
    <Label Width="100" Height="30" Background="Gray" Name="fieldNameLabel" /> 
    <Label Width="100" Height="30" Background="Silver" Name="fieldValueLabel" Content="{Binding fieldValue}" /> 
</StackPanel> 

Y aquí es el XAML para la ventana que hace referencia al control de usuario. En primer lugar el encabezado:

<Window x:Class="DAS1.Window1" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
xmlns:sys="clr-namespace:System;assembly=mscorlib" 
xmlns:me="clr-namespace:DAS1" 
Title="Window1" Height="580" Width="780"> 

A continuación, el propio control de usuario:

<me:LabeledField fieldName="Test" Width="200" Height="30" fieldValue="{Binding businessObjectField}"/> 

Si supiera de una pregunta más específica a pedir, me gustaría - pero puede alguien decirme por qué esto no funciona?

Respuesta

9

Resulta que en el XAML para el control del usuario, el enlace se ha especificado incorrectamente.

Originalmente era:

<Label Width="100" Height="30" Name="fieldValueLabel" Content="{Binding fieldValue}" /> 

Pero no había especificado el elemento al que pertenece ValorDelCampo. Cabe (suponiendo que mi control de usuario se denomina "LF":

<Label Width="100" Height="30" Name="fieldValueLabel" Content="{Binding ElementName=LF, Path=fieldValue}" /> 
+0

Finalmente BranchId' a'.! Pasé 5 horas pensando cosas fuera. TNX! – zdrsh

+0

¡Gracias! Solución simple era justo lo que necesitaba. – dex3703

5

Si desea vincular las propiedades del control, debe especificarlo en el enlace. Las vinculaciones se evalúan en relación con DataContext si su fuente no está explícitamente especificada, por lo que su enlace no se vincula a su control, sino al contexto heredado (que probablemente no tenga la propiedad a la que se está vinculando). Lo que necesita es:

<Label Width="100" Height="30" Name="fieldValueLabel" 
     Content="{Binding Path=fieldValue, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DAS1.LabeledField}}}" /> 
4

Usted realmente no necesita una propiedad de dependencia en el control de usuario, de hecho, usted debe esforzarse para mantener los controles de usuario sin nada especial en el código subyacente, Controles personalizados deben utilizarse para ese.

Debe definir su UserControl como esto (sin código detrás):

<UserControl x:Class="DAS1.LabeledField" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 
    <StackPanel Orientation="Horizontal"> 
     <Label Width="100" Height="30" Name="fieldNameLabel" Content="{Binding fieldName}" /> 
     <Label Width="100" Height="30" Name="fieldValueLabel" Content="{Binding field}" /> 
</StackPanel> 

A continuación, asegúrese de que su objeto de negocio implementa INotifyPropertyChanged, porque no se puede actualizar de su objeto de negocio de manera eficiente sin necesidad de modificar al menos esta mucho. El fieldName es solo un ejemplo de cómo puede vincular el nombre para mostrar en la etiqueta automáticamente a una propiedad en su objeto comercial.

Luego, simplemente asegúrese de que DataContext de su UserControl sea su objeto comercial.

¿Cómo funcionará? La propiedad Label.Content es DependencyProperty y admitirá el enlace en sí. Su objeto comercial implementa INotifyPropertyChanged y, por lo tanto, admite actualizaciones para el enlace - sin él, el sistema de enlace no recibe notificaciones cuando cambia el valor de su campo, independientemente de si lo enlazó a DependencyProperty en un extremo.

Y si desea reutilizar este control de usuario en otro lugar, simplemente coloque la instancia deseada de su objeto comercial en el DataContext del control deseado LabeledField. El enlace se conectará desde el DataContext.

+0

me gusta su solución porque es simple traté de ponerlo en práctica, sin embargo, sin éxito El XAML para el LabeledField se ve exactamente como usted.. sugirió el código detrás de ahora sólo contiene un constructor que llama a "InitializeComponents()", que es el predeterminado el XAML de Window1 se ve así:.. "me <: LabeledField fieldName =" Test "ValorDelCampo =" {Binding} point.lat "width =" 200" height = '30' />" me está dando errores que dicen 'La propiedad 'fieldName'/ 'ValorDelCampo' no se encontró en el tipo 'LabeledField''. ¿Alguna otra sugerencia? – Klay

+0

Usted debe tener un negocio objeto que expone las propiedades "field" y "fieldName" y establece ese objeto como DataContext del LabeledFie ld control. Por ejemplo "clase pública BusinessObject {public string fieldName {get {return "texto";}} campo public int {get {return 30;}}}" en el código, a continuación, en XAML: " –

+3

me gusta esta solución, pero esta solución no es muy adecuado para los controles de usuario que están diseñados para ser reutilizados/consume muchas veces en la misma interfaz de usuario Cada instancia se va a utilizar las mismas fijaciones ¿y si el dev quiere enviar datos basados ​​cadena diferente en cada instancia del control de usuario dado? Esta solución, en teoría, no debería funcionar. – IbrarMumtaz

Cuestiones relacionadas