2009-11-10 9 views
70

He algún objeto que se crea una instancia de código subyacente, por ejemplo, el XAML se llama window.xaml y dentro de los window.xaml.csobjetos de unión definido en el código subyacente

protected Dictionary<string, myClass> myDictionary; 

¿Cómo puedo unir este objeto para, por ejemplo, una vista de lista, usando solo marcas de XAML?

Actualización:

(Esto es exactamente lo que tengo en mi código de prueba):

<Window x:Class="QuizBee.Host.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="{Binding windowname}" Height="300" Width="300" 
    DataContext="{Binding RelativeSource={RelativeSource Self}}"> 
    <Grid> 
    </Grid> 
</Window> 

Y en CodeBehind

public partial class Window1 : Window 
{ 
    public const string windowname = "ABCDEFG"; 

    public Window1() 
    { 
     InitializeComponent(); 
    } 
} 

Supongamos que el título debería ser "ABCDEFG" derecho ? pero termina mostrando nada.

+1

Curiosamente, si cambio el orden de la asignación de propiedades de la ventana, no funciona. Si configuro la propiedad "Título" seguido de la propiedad "DataContext", no ocurre el enlace. ¿Alguien puede explicar esto? Ramesh

Respuesta

82

Puede establecer el DataContext para su control, forma, etc., así:

DataContext="{Binding RelativeSource={RelativeSource Self}}" 

Aclaración:

El contexto de datos que se establece en el valor anterior se debe hacer en cualquier elemento que "posea" el código subyacente, por lo que para una ventana, debe establecerlo la declaración de la ventana.

tengo su ejemplo de trabajo con este código:

<Window x:Class="MyClass" 
    Title="{Binding windowname}" 
    DataContext="{Binding RelativeSource={RelativeSource Self}}" 
    Height="470" Width="626"> 

El DataContext fija en este nivel, entonces es heredado por cualquier elemento en la ventana (a menos que cambie de forma explícita para un elemento secundario), por lo que después de ajustar el DataContext para la Ventana debería ser capaz de hacer enlaces directos a CodeBehind propiedades desde cualquier control en la ventana.

+0

El" Ser " "aquí significa el control, en lugar de toda la clase ventana, ¿verdad? – xandy

+0

Bastante extraño, lo que sigue es el código que tengo y no funciona como esperaba: clase parcial pública Ventana1: ventana { public const string windowname = "ABCDEFG"; public Window1() { InitializeComponent(); } } xandy

+8

Oh , ahora está bien, cambié el nombre de la ventana para ser propiedad en lugar de la variable pública pura y ¡puede mostrarse ahora! ¡Gracias! – xandy

0

En su código detrás, establezca el DataContext de la ventana en el diccionario. En su XAML, puede escribir:

<ListView ItemsSource="{Binding}" /> 

Esto vinculará el ListView al diccionario.

Para escenarios más complejos, esto sería un subconjunto de técnicas detrás del patrón MVVM.

0

Una forma sería crear un ObservableCollection (System.Collections.ObjectModel) y tener los datos del diccionario allí. Entonces deberías poder unir el ObservableCollection a tu ListBox.

En el XAML que debe tener algo como esto:

<ListBox ItemsSource="{Binding Path=Name_of_your_ObservableCollection" /> 
1

definir un conversor:

public class RowIndexConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, 
          object parameter, CultureInfo culture) 
    { 
     var row = (IDictionary<string, object>) value; 
     var key = (string) parameter; 
     return row.Keys.Contains(key) ? row[ key ] : null; 
    } 

    public object ConvertBack(object value, Type targetType, 
           object parameter, CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 

se unen a una definición personalizada de un diccionario. Hay muchas anulaciones que he omitido, pero el indexador es el más importante, porque emite el evento de propiedad cambiada cuando se cambia el valor. Esto es obligatorio para el enlace de origen a destino.

public class BindableRow : INotifyPropertyChanged, IDictionary<string, object> 
{ 
    private Dictionary<string, object> _data = new Dictionary<string, object>(); 

    public object Dummy // Provides a dummy property for the column to bind to 
    { 
     get 
     { 
      return this; 
     } 
     set 
     { 
      var o = value; 
     } 
    } 


    public object this[ string index ] 
    { 
     get 
     { 
      return _data[ index ]; 
     } 
     set 
     { 
      _data[ index ] = value; 
      InvokePropertyChanged(new PropertyChangedEventArgs("Dummy")); // Trigger update 
     } 
    } 


} 

En su archivo .xaml, utilice este convertidor. En primer lugar hacer referencia a ella:

<UserControl.Resources> 
    <ViewModelHelpers:RowIndexConverter x:Key="RowIndexConverter"/> 
</UserControl.Resources> 

Entonces, por ejemplo, si el diccionario tiene una entrada donde la clave es "Nombre", a continuación, para unirse a la misma: utilizar

<TextBlock Text="{Binding Dummy, Converter={StaticResource RowIndexConverter}, ConverterParameter=Name}"> 
1

Haga su propiedad "nombre de ventana" una DependencyProperty y mantener el resto igual.

22

Aunque la respuesta de Guy es correcta (y probablemente se ajusta a 9 de cada 10 casos), vale la pena señalar que si intenta hacer esto desde un control que ya tiene su DataContext configurado más arriba en la pila, restablecerá este cuando configura DataContext de nuevo:

DataContext="{Binding RelativeSource={RelativeSource Self}}" 

Esto, por supuesto, romperá sus enlaces existentes.

Si este es el caso, debe establecer RelativeSource en el control que está intentando vincular, en lugar de su elemento primario.

es decir, por la unión a las propiedades de un control de usuario:

Binding Path=PropertyName, 
     RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}} 

Teniendo en cuenta lo difícil que puede ser momento para ver lo que está pasando con el enlace de datos, es importante tener esto en cuenta, incluso si usted encuentra que el establecimiento RelativeSource={RelativeSource Self} trabaja actualmente :)

+1

Silverlight 4 no es compatible con FindAncestor. Sin embargo, debe hacerlo de esta manera para implementar FindAncestor tal como se describe en este sitio. [http://blog.thekieners.com/2010/09/08/relativesource-binding-with-findancestor-mode-in-silverlight/](http://blog.thekieners.com/2010/09/08/ relativesource-binding-with-findancestor-mode-in-silverlight /) – ShawnFeatherly

107

Hay una manera mucho más fácil de hacer esto. Puede asignar un nombre a su ventana o UserControl, y luego vincular por ElementName.

Window1.xaml

<Window x:Class="QuizBee.Host.Window1" 
     x:Name="Window1" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 

    <ListView ItemsSource="{Binding ElementName=Window1, Path=myDictionary}" /> 
</Window> 

Window1.xaml.cs

public partial class Window1:Window 
{ 
    // the property must be public, and it must have a getter & setter 
    public Dictionary<string, myClass> myDictionary { get; set; } 

    public Window1() 
    { 
     // define the dictionary items in the constructor 
     // do the defining BEFORE the InitializeComponent(); 

     myDictionary = new Dictionary<string, myClass>() 
     { 
      {"item 1", new myClass(1)}, 
      {"item 2", new myClass(2)}, 
      {"item 3", new myClass(3)}, 
      {"item 4", new myClass(4)}, 
      {"item 5", new myClass(5)}, 
     }; 

     InitializeComponent(); 
    } 
} 
+0

Esto es exactamente lo que estaba buscando ... gracias. –

+24

+1 para establecer propiedades vinculadas ANTES de InitializeComponent() –

+2

Tuve que cambiar x: Nombre (error de compilador CS0542). Entonces ElementName necesita ser cambiado en consecuencia. –

0

que estaba teniendo este mismo problema, pero la mía no era porque me estaba poniendo una variable local. .. Estaba en una ventana secundaria, y necesitaba establecer un DataContext relativo que acabo de agregar a la ventana XAML.

<Window x:Class="Log4Net_Viewer.LogItemWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    DataContext="{Binding RelativeSource={RelativeSource Self}}" 
    Title="LogItemWindow" Height="397" Width="572"> 
4

Sólo un poco más aclaraciones: una propiedad sin 'conseguir', 'conjunto' no será capaz de obligarse

que estoy enfrentando el caso al igual que el caso del autor de la pregunta. Y debo tener las siguientes cosas para que el enlace funcione correctamente:

//(1) Declare a property with 'get','set' in code behind 
public partial class my_class:Window { 
    public String My_Property { get; set; } 
    ... 

//(2) Initialise the property in constructor of code behind 
public partial class my_class:Window { 
    ... 
    public my_class() { 
    My_Property = "my-string-value"; 
    InitializeComponent(); 
    } 

//(3) Set data context in window xaml and specify a binding 
<Window ... 
DataContext="{Binding RelativeSource={RelativeSource Self}}"> 
    <TextBlock Text="{Binding My_Property}"/> 
</Window> 
+3

¿Cómo se puede tener una propiedad sin 'get' y 'set'? ¿No sería eso un campo y no una propiedad? – kjbartel

Cuestiones relacionadas