2008-12-22 10 views
24

En Silverlight 2 estoy usando un control de usuario que hereda el contexto de datos de la página en la que está incrustado. Este contexto de datos contiene texto de pregunta, un tipo de pregunta y una colección de respuestas. En el control del usuario hay un cuadro de lista que está vinculado a la colección de respuestas. Como se muestra a continuación:Acceda al contexto de datos principal en el cuadro de lista en Silverlight

<ListBox DataContext="{Binding}" x:Name="AnswerListBox" ItemContainerStyle="{StaticResource QuestionStyle}" Grid.Row="1" Width="Auto" Grid.Column="2" ItemsSource="{Binding Path=AnswerList}" BorderBrush="{x:Null}" />  

Este cuadro de lista tiene un estilo asociado para mostrar las respuestas en forma de botones de opción o casillas de verificación (que me gustaría ocultar o mostrar en función del tipo de pregunta) como:

<Style TargetType="ListBoxItem" x:Key="QuestionStyle"> 
      <Setter Property="Template"> 
       <Setter.Value> 
        <ControlTemplate TargetType="ListBoxItem">      
         <StackPanel Background="Transparent" > 
          <RadioButton Visibility="{Binding Path=QuestionType, Converter={StaticResource QuestionTypeConverter}, ConverterParameter='RadioButtonStyle'}" Height="auto" Margin="0,0,0,10" IsChecked="{TemplateBinding IsSelected}" IsHitTestVisible="False" Content="{Binding Path=AnswerText}"> 
          </RadioButton> 
          <CheckBox Visibility="{Binding Path=QuestionType, Converter={StaticResource QuestionTypeConverter}, ConverterParameter='CheckBoxStyle'}" Height="auto" Margin="0,0,0,10" Content="{Binding Path=AnswerText}"> 
          </CheckBox> 
         </StackPanel>             
        </ControlTemplate> 
       </Setter.Value> 
      </Setter> 
     </Style> 

Así que mi pregunta es: ¿cómo accedes al contexto de datos padre para obtener QuestionType (ya que esta es una propiedad en el control de datos del mismo contexto, no una propiedad en un AnswerItem en la AnswerList)?

Alternativamente, ¿existe una mejor manera de cambiar estilos dinámicamente en el xaml en función de un valor de enlace?

+1

¿Tiene alguna forma de cambiar su respuesta aceptada? El siguiente, por Roboblob, es una respuesta correcta. La respuesta aceptada es incorrecta para Silverlight y engañosa. –

Respuesta

55

En Silverlight 3 y versiones posteriores puede usar el enlace Elemento a Elemento y señalar los controles DataContext y algunas propiedades en mi ejemplo su propiedad de Umbral.

Así que primero el nombre de su control (por ejemplo, en mi ejemplo la x: Name = "control")

<UserControl x:Class="SomeApp.Views.MainPageView" x:Name="control" > 

continuación, dentro de este control en su ListBox ItemTemplate puede acceder DataContext padres así:

<ListBox ItemsSource="{Binding Path=SomeItems}" > 
     <ListBox.ItemTemplate> 
     <DataTemplate> 
      <StackPanel Orientation="Horizontal"> 
      <TextBlock Text="{Binding ElementName=control, Path=DataContext.Threshold}"/> 
      </StackPanel> 
     </DataTemplate> 
     </ListBox.ItemTemplate>   
     </ListBox> 
+4

importante que no debe perderse que necesita poner explícitamente 'DataContext'. anteriormente había abandonado un intento de hacer esto porque me las arreglé para olvidar poner 'DataContext' –

+0

@roboblob - ¿Por casualidad sabes una buena manera de hacer esto dentro de un DataForm (no funciona de la misma manera que se muestra en mi publicación abajo) –

+0

@Roboblob - Solución inteligente para un problema común. Bajaré-vote el que está marcado como "la" respuesta, ya que es engañoso y de hecho perdió nuestro tiempo hasta que vimos el suyo. –

1

He estado luchando con un problema similar. El mío consiste en un cuadro combinado que se muestra para cada elemento de lista. El alto nivel DataContext está ligado a mi modelo de vista (MVVM) y se ve así:

class ViewModel{ 
    ObservableCollection<ComboboxListItemType> DataForTheComboBoxList; 
    ObservableCollection<MyDataType> DataForTheListBox; 
    ... 
} 

Debido a que el cuadro combinado está dentro del ItemTemplate (= DataTemplate) para el cuadro de lista, el DataContext para cada elemento de la lista se establece en el elemento apropiado en DataForTheListBox, el cuadro combinado ya no puede ver el DataForTheComboBoxList que necesita del DataContext de nivel superior.

Mi (sucia, fea) solución implica establecer la lista completa de combobox en cada elemento de la lista, por lo que se vuelve visible para el DataContext en este elemento de la lista.

Primero se hace una clase parcial para su tipo de datos listbox. (En general, esto vendrá de una referencia de servicio, por lo que no puede tocar el código generado directamente sin perderlo potencialmente). Esta clase parcial contiene una nueva propiedad en referencia a su cuadro combinado Tipo de lista de elementos:

public partial class MyDataType 
{ 
    private ObservableCollection<ComboboxListItemType> m_AllComboboxItems; 
    public ObservableCollection<ComboboxListItemType> AllComboboxItems 
    { 
     get { return m_AllComboboxItems; } 
     set 
     { 
      if (m_AllComboboxItems != value) 
      { 
       m_AllComboboxItems = value; 
       RaisePropertyChanged("AllComboboxItems"); 
      } 
     } 
    } 
} 

Usted tiene que establecer esta propiedad en cada elemento de la colección DataForTheListBox

// in ViewModel class 
foreach(var x in this.DataForTheListBox) 
{ 
    x.AllComboboxItems = this.DataForTheComboBoxList; 
} 

Luego de vuelta en su XAML:

<DataTemplate x:Key="ListBoxItemTemplate"> 
    ... 
    <Combobox 
     ItemsSource="{Binding AllComboboxItems}" 
     SelectedItem="{Binding CurrentBlah}"/> 
</DataTemplate> 

No se olvide que para el cuadro combinado para mostrar correctamente el elemento actual, el elemento seleccionado debe referirse al real elemento en ItemsSource del cuadro combinado. Si está obteniendo datos de un servicio web que tiene ID u objetos para representar el elemento para el cuadro combinado, debe volver a referenciarlos para que apunten a la colección real.

1

Una de las mejores cosas que puedes hacer con silverlight es usar el atributo Tag para almacenar una referencia al objeto al que está vinculado.

En primer lugar, en su clase, declarar una propiedad como esta

public IMyObject Current 
{ 
    get {return this;} 
} 

A continuación, en el mando a elevar el evento en que se puede obtener una referencia al objeto

var fe= (FrameworkElement) sender; 
var src = fe.Tag as IMyObject; 

Así que ahora que tengo el objeto, es razonable que un objeto tenga referencia a su elemento principal, entonces se une a

Current.Parent.QuestionType 
Cuestiones relacionadas