DataContext özelliğini kullanarak XAML'deki bir pencerede ViewModel'i nasıl ayarlayabilirim?


96

Soru hemen hemen her şeyi söylüyor.

Bir pencerem var ve DataContext'i ViewModel'e tam ad alanını kullanarak ayarlamaya çalıştım, ancak yanlış bir şey yapıyor gibiyim.

<Window x:Class="BuildAssistantUI.BuildAssistantWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    DataContext="BuildAssistantUI.ViewModels.MainViewModel">

Mike Nakis'in ardından, ViewModel'i manuel olarak oluşturmaya ve içindeki olaylara abone olmaya çalışıyordum, ancak çerçevenin başka bir ViewModel oluşturduğunu bulmak için. Bu nedenle, abone olduğum viewModel, görünüme eklenmiş olan model değildi.
jlady

Bu kendini ViewModel başlatmasını ayrıca, sen olduğunu anlamına mı geliyor da başka bir şekilde ViewModel tipini belirten? Yapıcı parametreleri gerektiren görünüm modellerinin ikincil bir avantajı, çerçevenin bunları başlatamaması veya bu parametreler için varsayılan değerleri iletmesi gerektiğidir, bu durumda çerçeve tarafından başlatmayı kolayca algılayabilirsiniz.
Mike Nakis

XAML tasarımcısının da görünüm modellerini örnekleyebilmesi gerekebilir, ancak bu tasarımcı benim için hiçbir zaman yararlı olmadı (sadece sorunlara neden oluyor) bu yüzden kullanmıyorum, bu yüzden kişisel olarak bu kullanım durumunu umursamıyorum.
Mike Nakis

Yanıtlar:


113

Diğer kişilerin sağladığı (iyi ve doğru) çözüme ek olarak, XAML'de ViewModel'i belirtmenin, ancak yine de belirli ViewModel'i View'dan ayırmanın bir yolu vardır. Bunları ayırmak, izole edilmiş test senaryoları yazmak istediğinizde kullanışlıdır.

App.xaml'de:

<Application
    x:Class="BuildAssistantUI.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:BuildAssistantUI.ViewModels"
    StartupUri="MainWindow.xaml"
    >
    <Application.Resources>
        <local:MainViewModel x:Key="MainViewModel" />
    </Application.Resources>
</Application>

MainWindow.xaml içinde:

<Window x:Class="BuildAssistantUI.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    DataContext="{StaticResource MainViewModel}"
    />

Vay canına ... teşekkürler. Bunu zaten yanıt olarak işaretledim, ancak eklemeniz çok takdir ediliyor. Kullanacak.
Nicholas

@Nicholas: Diğer cevap soru için mükemmel, bu yüzden kararınıza katılıyorum
Merlyn Morgan-Graham

8
Bu yaklaşımın her MainWindow örneği için aynı ViewModel örneğini kullandığını unutmayın. Bu durumda ima ettiği gibi pencere tek örnekli ise bu sorun değil, ancak MDI veya sekmeli uygulama durumunda olduğu gibi pencerenin birden çok örneğini gösteriyorsanız sorun yok.
Josh

1
Aslında Josh'un yanıtı, size DataContext'te yazım güvenliği sağladığından daha iyidir. Böylece, bazı özellik adlarının / yollarının yazımını yapma endişesi olmadan doğrudan DataContext'e bağlanabilirsiniz.
Josh M.

149

Bunun yerine bunu deneyin.

<Window x:Class="BuildAssistantUI.BuildAssistantWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:VM="clr-namespace:BuildAssistantUI.ViewModels">
    <Window.DataContext>
        <VM:MainViewModel />
    </Window.DataContext>
</Window>

3
Bu seçeneği en çok seviyorum. VM yalnızca MainWindow için kullanılıyorsa daha temiz görünür.
Andrew Grothe

13
WindowÖğe üzerindeki bir özniteliği kullanarak veri bağlamını ayarlamanın bir yolu var mı DataContext="VM:MainWindowViewModel"?
Oliver

Doğru yol bu!
JavierIEH

Bir yolun diğerinden neden daha iyi olduğunu tam olarak anlamıyorum. Ayrıca, bazı insanların "Dinamik Kaynak" kullandığını gördüklerime kıyasla bu iki yoldan da farkı tam olarak görmüyorum. Bu nedir?
Travis Tubbs

1
@Oliver uygulamak zorunda kalırsınız, bunu VM'lerde MarkupExtensionasla yapmazsınız , ancak bunu yalnızca bir dönüştürücü örneğinin mevcut olduğundan emin olmak için dönüştürücülerle yapabilir ve dönüştürücü ad alanındaki noktaları ="{converters:SomethingConverter}"ima ederek xaml'den doğrudan çağırabilirsiniz xmlns:converters. public abstract class BaseValueConverter<T> : MarkupExtension, IValueConverter where T : class, new() { private static T _converter; public override object ProvideValue(IServiceProvider serviceProvider) { return _converter ?? (_converter = new T()); } }
Whazz

11

MainViewModel'i başlatmanız ve onu veri bağlamı olarak ayarlamanız gerekir. İfadenizde bunu sadece dize değeri olarak düşünün.

     <Window x:Class="BuildAssistantUI.BuildAssistantWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:BuildAssistantUI.ViewModels">
      <Window.DataContext>
        <local:MainViewModel/>
      </Window.DataContext>

Teşekkürler, bunu yaptığını düşündüm.
Nicholas

3

Catel'i denemek isteyebilirsin . Bir DataWindow sınıfı (Pencere yerine) tanımlamanıza olanak tanır ve bu sınıf, sizin için otomatik olarak görünüm modelini oluşturur. Bu şekilde, ViewModel'in bildirimini orijinal gönderinizde yaptığınız gibi kullanabilirsiniz ve görünüm modeli yine de oluşturulacak ve DataContext olarak ayarlanacaktır.

Örnek için bu makaleye bakın .


3

Görünüm modelini belirtmenin de şu yolu vardır:

using Wpf = System.Windows;

public partial class App : Wpf.Application //your skeleton app already has this.
{
    protected override void OnStartup( Wpf.StartupEventArgs e ) //you need to add this.
    {
        base.OnStartup( e );
        MainWindow = new MainView();
        MainWindow.DataContext = new MainViewModel( e.Args );
        MainWindow.Show();
    }
}

<Rant>

Önceden önerilen tüm çözümler MainViewModel, parametresiz bir kurucuya sahip olmayı gerektirir .

Microsoft, sistemlerin parametresiz kurucular kullanılarak oluşturulabileceği izlenimine sahiptir. Siz de bu izlenimin altındaysanız, devam edin ve diğer çözümlerden bazılarını kullanın.

Kurucuların parametrelere sahip olması gerektiğini ve bu nedenle nesnelerin somutlaştırılmasının sihirli çerçevelerin ellerine bırakılamayacağını bilenler için, görünüm modelini belirlemenin doğru yolu yukarıda gösterdiğimdir.

</Rant>

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.