Home > Software design >  How can I create only one instance of a DataContext for multiple windows?
How can I create only one instance of a DataContext for multiple windows?

Time:02-11

So I have a WPF program in which I have a ViewModel and several windows. I usually add the DataContext for my ViewModel like this:

<Window.DataContext>
    <local:PrintView x:Name="printerView"/>
</Window.DataContext>

But if I do it that way, I have the problem that multiple instances of the ViewModel are created, one instance for each window. Which means that if I change a property in one window, the same property of the other window doesn't change.

Now I had done it in such a way that I define it in App.xaml like this:

<Application.Resources>

    <ResourceDictionary>
        <local:PrintView x:Key="printView"/>
    </ResourceDictionary>
</Application.Resources>

And address in each window like this:

DataContext="{StaticResource printView}"

But now the problem is that I want to create the whole thing without the App.Xaml. Does anyone have any idea how I can create the same result without App.xaml? As well as without libraries.

I'm working with .NET Framework 4.8

EDIT

I have now implemented the solution from @mm8. However, it still doesn't seem to work. Everything works in the Xaml part and I have access to the properties. However, there are problems in the code behind, namely when I select a value in a window and save it in the property:

SecondWindow

And so save the selected value in the property:

SelectedItem="{Binding selected_printer, Mode=TwoWay}"

But I then want to access this changed value in the other window, whether like this:

 var vm = (ViewModel)this.DataContext;
 vm.selected_printer

or like this:

ApplicationService.Instance.PrintView.selected_printer

No matter how I try to access the previously changed property in the other window, the property doesn't update in the other window with the new value.

So this value: SecondWindow is not transferred to the other window and is not updated

My Selected Printer defined:

 private string _selected_printer;
    public string selected_printer
    {
        get
        {
            return _selected_printer;
        }
        set
        {
            _selected_printer = value;
            NotifyPropertyChanged(nameof(selected_printer));
        }
    }

My ViewModel defined:

  public class PrintView: INotifyPropertyChanged

My Property Changed Stuff:

 public event PropertyChangedEventHandler PropertyChanged;

    public void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

CodePudding user response:

You don't need to use App.xaml to be able to create global resources. You could create your own application-wide service class and set up your view model(s) there:

public sealed class ApplicationService
{
    private ApplicationService() { }

    public static ApplicationService Instance { get; } = new ApplicationService();

    public PrintView PrintView { get; } = new PrintView();
}

Usage:

DataContext="{Binding PrintView, Source={x:Static local:ApplicationService.Instance}}"

This is basically how a view-model locator works (assuming PrintView is actually a view model despite its name...)

  • Related