2009-05-14 7 views
13

Parece que hay dos formas principales para definir DataContext en WPF:¿Cuál es la ventaja de establecer DataContext en código en lugar de XAML?

  • ya sea en el código así:

App.xaml.cs (tomado de la WPF MVVM Toolkit template):

public partial class App : Application 
{ 
    private void OnStartup(object sender, StartupEventArgs e) 
    { 
     // Create the ViewModel and expose it using the View's DataContext 
     MainView mainView = new MainView(); 
     MainViewModel mainViewModel = new MainViewModel(); 
     mainViewModel.LoadCustomers("c:\\testdata2\\Customers.xml"); 
     mainView.DataContext = mainViewModel; 
     mainView.Show(); 
    } 
} 
  • o en XAML así:

Window1.xaml:

<DockPanel> 
    <StackPanel 
     HorizontalAlignment="Left" 
     DockPanel.Dock="Top" 
     Orientation="Horizontal"> 
     <StackPanel.DataContext> 
      <local:CustomerViewModel /> 
     </StackPanel.DataContext> 
     <TextBlock Text="{Binding Path=FirstName}" /> 
     <TextBlock Text=" " /> 
     <TextBlock Text="{Binding Path=LastName}" /> 
    </StackPanel> 

    <StackPanel 
     HorizontalAlignment="Left" 
     VerticalAlignment="top" 
     DockPanel.Dock="Top" 
     Orientation="Horizontal"> 
     <ListBox ItemsSource="{Binding Source={StaticResource FileNames}}" /> 
    </StackPanel> 

    <StackPanel 
     HorizontalAlignment="Left" 
     VerticalAlignment="top" 
     DockPanel.Dock="Top" 
     Orientation="Horizontal"> 
     <ComboBox 
      ItemsSource="{Binding Source={StaticResource Directories}}" 
      SelectedIndex="0" /> 
    </StackPanel> 

    <StackPanel 
     HorizontalAlignment="Left" 
     VerticalAlignment="top" 
     DockPanel.Dock="Top" 
     Orientation="Horizontal"> 
     <StackPanel.DataContext> 
      <local:SystemInformationViewModel /> 
     </StackPanel.DataContext> 
     <TextBlock Text="{Binding Path=CurrentTime}" /> 
    </StackPanel> 
</DockPanel> 

Una ventaja de que la definición de la DataContext en XAML tiene es que sus datos aparece en el modo de diseño de Expression Blend y Expression Blend le permite hacer mucho dentro de la GUI, por ejemplo elija campos de su fuente de datos, etc. as shown here.

He leído que los objetos vinculados ADO.NET no pueden vincularse en XAML (aunque no veo por qué podría escribir un contenedor mínimo para ellos al que pueda vincular desde XAML).

extraño que el equipo de WPF en la fabricación de las plantillas de WPF MVVM definir el DataContext en el código, que muy rápidamente hace que sea imposible para editar sus vistas en Expression Blend, ya que sus datos no aparece en el modo de diseño que es a menudo una parte significativa del diseño.

Así que estoy pensando que debe ser una ventaja en el camino a la configuración de DataContext en el código en lugar de XAML, ¿alguien sabe lo que es?

Respuesta

1

Tenerlo en codebehind hace que sea fácil inyectar el contexto de datos usando la unidad.

+0

¿Hay una mejor solución de ambos mundos para esto? ¿Esto significa que si utiliza la Biblioteca de aplicaciones compuestas/Unity que básicamente puede cortar y pegar de Expression Blend o hay una manera simple de, p. ¿se han burlado DataContexts por defecto en XAML que los diseñadores pueden usar en Blend? –

+2

Bloody good question mate. –

+1

ver mi respuesta en el DataobjectProvider. Se podría usar como fachada para delegar la creación de instancias y usar algo proveniente de DI. –

4

No me gusta la idea de tener Expression Blend intente crear una instancia de mis objetos de datos.

Configuré el código de DataContext mediante el cual puedo usar Inyección de dependencia para inyectar los objetos, servicios, proveedores o cualquier otra cosa que estoy utilizando para encontrar mi código.

1

Podría haber una especie de solución para esto, utilizando DataObjectProvider para enmascarar el hecho de que los datos se instancian fuera de XAML.

Indicará el tipo de DataContext, que debería ser suficiente para que Blend recoja las propiedades.

No he intentado esto todavía, así que tómelo con un grano de sal, pero sin duda vale la pena investigarlo. Artículo

15

Usted puede (tal vez en 2009 que no podía) obtener lo mejor de ambos mundos mediante el atributo d:DataContext.No es necesario nada de eso ViewModelLocator craziness si usted no está listo para eso todavía :-)

En primer lugar asegúrese de que ha siguiente espacio de nombres XML definido en su elemento raíz:

xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 

A continuación, puede añadir el siguiente atributo a un elemento en su xaml:

d:DataContext="{d:DesignInstance IsDesignTimeCreatable=True, Type=vm:CustomerInsightViewModel}"

en su código subyacente xaml:

public CustomerInsightUserControl() 
    { 
     InitializeComponent(); 

     if (!DesignerProperties.IsInDesignTool) 
     { 
      DataContext = new CustomerInsightViewModel(); 
     } 
    } 

Luego, en su modelo de vista:

public CustomerInsightViewModel() 
    { 
     if (IsInDesignMode) 
     { 
      // Create design time data 
      Customer = new Customer() { 
       FirstName=... 
      } 
     } 
     else { 
      // Create datacontext and load customers 
     } 
    } 

no se pierda la IsDesignTimeCreatable=True o de lo contrario no se mezcla una instancia de la clase

+1

Si obtiene un error de tiempo de compilación iniciando "La propiedad 'DataContext' debe estar en el espacio de nombres predeterminado ...", la solución para esto está en http://stackoverflow.com/q/8303803/62278 –

0

En mi experiencia, lo mejor es diseñar una interfaz de diseño contra al menos una muestra de los datos que presentará. Hacer lo contrario es estar ciego a las ideas baratas y los descuidos costosos.

Cuestiones relacionadas