В чем преимущество установки DataContext в коде вместо XAML? - PullRequest
13 голосов
/ 14 мая 2009

Существует два основных способа определения DataContext в WPF:

  • либо в коде , например:

App.xaml.cs (взято из шаблона WPF MVVM Toolkit ):

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();
    }
}
  • или в 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 при создании шаблонов WPF MVVM определяет DataContext в коде , что очень быстро делает практически невозможным редактирование ваших представлений в Expression Blend, поскольку ваши данные не отображаются в режиме разработки что часто является значительной частью макета.

Так что я думаю, что должно быть какое-то преимущество на пути к установке DataContext в коде вместо XAML, кто-нибудь знает, что это такое?

Ответы [ 7 ]

15 голосов
/ 01 августа 2010

Вы можете (возможно, в 2009 году не смогли) получить лучшее из обоих миров, используя атрибут d:DataContext. Вам не нужно ничего из этого ViewModelLocator сумасшествия , если вы еще не готовы к этому: -)

Сначала убедитесь, что у вас есть следующее пространство имен XML, определенное в вашем корневом элементе:

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

Затем вы можете добавить следующий атрибут к элементу в вашем xaml:

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

В вашем коде xaml:

    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 не создаст экземпляр вашего класса

5 голосов
/ 14 мая 2009

Мне не нравится идея, что Expression Blend попытается создать экземпляры моих объектов данных.

Я устанавливаю DataContext с помощью кода, где я могу использовать Dependency Injection, чтобы внедрить подходящие объекты, услуги, поставщиков или что еще я использую для поиска своего кода.

1 голос
/ 31 марта 2011

Также должна быть возможность использовать ObjectDataProvider для создания фабрики объектов с использованием 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

1 голос
/ 04 декабря 2009

См. Статью Роба о данных времени проектирования в Blend: http://www.robfe.com/2009/08/design-time-data-in-expression-blend-3/

1 голос
/ 14 мая 2009

Для этого может быть какое-то решение, использующее DataObjectProvider для маскировки того факта, что данные создаются вне XAML.

В нем будет указан тип DataContext, которого должно быть достаточно, чтобы Blend подобрал свойства.

Я еще не пробовал, так что возьмите его с крошкой соли, но это, безусловно, стоит исследовать.

1 голос
/ 14 мая 2009

Наличие его в codebehind позволяет легко вводить текст данных с помощью единицы.

0 голосов
/ 21 марта 2011

По моему опыту, лучше всего спроектировать макет интерфейса по крайней мере на примере данных, которые он будет представлять. Делать иначе - значит быть слепым к дешевым прозрениям и дорогостоящим упущениям.

...