В чем преимущество настройки DataContext в коде вместо XAML?
Кажется, существуют два основных способа определения DataContext в WPF:
App.xaml.cs(взято из 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 DataContext
MainView mainView = new MainView();
MainViewModel mainViewModel = new MainViewModel();
mainViewModel.LoadCustomers("c:\\testdata2\\Customers.xml");
mainView.DataContext = mainViewModel;
mainView.Show();
}
}
- или в XAML следующим образом:
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>
Одно из преимуществ, заключающееся в том, что определение DataContext в XAML состоит в том, что ваши данные отображаются в режиме разработки Expression Blend, а Expression Blend позволяет делать довольно много в графическом интерфейсе, например. выберите поля из источника данных и т.д. как показано здесь.
Я прочитал, что привязка объектов ADO.NET не может быть привязана к XAML (хотя я не понимаю, почему вы могли бы написать минимальную оболочку для них, с которой вы могли бы связываться с XAML).
Странно, что команда WPF при создании шаблонов MVVM WPF определяет DataContext в коде, что очень быстро делает невозможным редактировать ваши представления в Expression Blend, поскольку ваши данные не отображаются в дизайне режим, который часто является значительной частью макета.
Итак, я думаю, что должно быть какое-то преимущество по пути к установке DataContext в коде вместо XAML, кто-нибудь знает, что это такое?
Ответы
Ответ 1
Вы можете (возможно, в 2009 году вы не смогли) получить лучшее из обоих миров, используя атрибут d:DataContext
. Вам не нужен какой-либо из ViewModelLocator
craziness, если вы еще не готовы к этому: -)
Сначала убедитесь, что в корневом элементе указано следующее пространство имен XML:
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
Затем вы можете добавить следующий атрибут к элементу в вашем xaml:
d:DataContext="{d:DesignInstance IsDesignTimeCreatable=True, Type=vm:CustomerInsightViewModel}"
В вашем xaml codebehind:
public CustomerInsightUserControl()
{
InitializeComponent();
if (!DesignerProperties.IsInDesignTool)
{
DataContext = new CustomerInsightViewModel();
}
}
Затем в вашей ViewModel:
public CustomerInsightViewModel()
{
if (IsInDesignMode)
{
// Create design time data
Customer = new Customer() {
FirstName=...
}
}
else {
// Create datacontext and load customers
}
}
Не пропустите IsDesignTimeCreatable=True
, иначе Blend не будет создавать экземпляр класса
Ответ 2
Мне не нравится идея использования Expression Blend для создания экземпляров объектов данных.
Я устанавливаю DataContext через код, где я могу использовать Dependency Injection для инъекции правильных объектов, служб, поставщиков или того, что еще я использую, чтобы найти свой код.
Ответ 3
Наличие в коде позволяет легко вводить datacontext, используя единство.
Ответ 4
Это может быть какое-то решение, используя DataObjectProvider для маскирования того факта, что данные создаются вне XAML.
Он укажет, что такое тип DataContext, которого должно быть достаточно, чтобы Blend мог получить свойства.
Я еще не пробовал этого, поэтому возьмите его с солью, но это, безусловно, стоит исследовать.
Ответ 5
См. статью Роба о данных времени разработки в Blend: http://www.robfe.com/2009/08/design-time-data-in-expression-blend-3/
Ответ 6
Также должно быть возможно использовать ObjectDataProvider для создания объекта factory с использованием Unity или других IOC, как это подразумевается здесь...
http://social.msdn.microsoft.com/Forums/en/wpf/thread/1ff9e90e-302e-436e-bab3-ca4bad2b85af
в частности...
http://www.codeproject.com/Articles/43806/WPF-Ninject-Dojo-The-Data-Provider.aspx
Ответ 7
По моему опыту, лучше всего разработать макет интерфейса по меньшей мере по образцу данных, которые он будет представлять. Сделать иначе - значит быть слепым к дешевым идеям и дорогим оплошностям.