1

So I am just getting into databinding & MVVM and I am having a small issue with this one thing.

I have a WPF project with a seperate class called Player

In my MainWindow class I am setting the DataContext to a instance of that Player class

public partial class MainWindow : Window
    {
        Player player = new Player();
        public MainWindow()
        {
            InitializeComponent();
            DataContext = player;
        }
    }

In that class I have a property in which I am setting a value in the constructor.

public class Player : INotifyPropertyChanged
    {
        private string _Firstname;

        public Player()
        {
            _Firstname = "William";
        }
        public string Firstname
        {
            get { return _Firstname; }
            set { _Firstname = value; }
        }


        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged(string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }

And then in the XAML there is some simple databinding logic going on for the TextBox

<TextBox Name="TbName" HorizontalAlignment="Left" Height="23" Margin="243,119,0,0" TextWrapping="Wrap" Text="{Binding Path=Firstname}" VerticalAlignment="Top" Width="120"/>

Now.. Let's say I had another class called I don't know.. Acheivments.. How would I set the Text of another control to a property of that class? I would have to set another DataContext and I don't know how to set multiple datacontexts.

QUESTION: How do I properly set two datacontexts so I can bind different classes to different controls?

mm8
  • 163,881
  • 10
  • 57
  • 88
Jess Chan
  • 391
  • 2
  • 14
  • You say "another class". You would have to create an instance of this class somewhere. There are multiple options: using [static binding](https://stackoverflow.com/q/936304/1997232), creating a property in main window viewmodel (see @mm8 answer), which return instance of that class and e.g. bind `ContentControl.Content` to it (will require data template to work), simply binding `DataContext` to that instance, etc. – Sinatr May 16 '18 at 08:01
  • `DataContext` just a convenient way to share data through visual tree. In MVVM pattern, binding ViewModel to `DataContext` of View's root element is only because ViewModel is contained all data needed by View. So you should write a appropriate ViewModel that expose all data like `Player`, `Acheivments`... through its properties for your `MainWindow`. – Alex.Wei May 16 '18 at 08:13

2 Answers2

7

You can only set the DataContext property to a single object, but the type of this object may contain multiple properties that you can bind to:

class ViewModel
{
    public Player Player { get; } = new Player();
    public Achievement Achievement { get; } = new Achievement();
}

public MainWindow()
{
    InitializeComponent();
    DataContext = new ViewModel();
}

XAML:

<TextBox Text="{Binding Path=Person.Firstname}" />
...
<TextBlock Text="{Binding Achievement.SomeProperty}" />
mm8
  • 163,881
  • 10
  • 57
  • 88
  • The one who downvoted this answer should probably do some reading into how databinding and datacontexts work. – mm8 May 16 '18 at 08:04
  • 1
    That's exactly what I was looking for! I tried making ViewModel a seperate class a few days ago and binding it like that with the . didnt work I am not sure why, I am going to try this and and see what I can do, great answer! – Jess Chan May 16 '18 at 08:06
  • "I am not sure why" - as said before, you forgot the initialization, i.e. the `new Player()` part in `public Player Player { get; } = new Player();` – Clemens May 16 '18 at 11:20
-4

As Best you create different List's like this:

  public ObservableCollection<Player> ListOne = new ObservableCollection<Player>();

after that you fill this list with your values.

now you Need to give your TextBox in XMAL a DataTemplate with The Class Player.

                  <TextBox.ItemTemplate>
                        <DataTemplate x:DataType="data:Bilder">
                            //Whatever you want to bind here.
                        </DataTemplate>
                    </TextBox.ItemTemplate>

At the end you can bind now different Lists to different Controls.

TbName.source = ListOne;
Hubii
  • 348
  • 1
  • 14
  • How would creating an ObservableCollection allow you to bind to a property of a different type such as Achievement...? – mm8 May 16 '18 at 08:05
  • This answer is plain nonsense. There is neither an ItemTemplate nor a source property in class TextBox. Besides what was mentioned before. How could it get an upvote? It should urgently be deleted. – Clemens May 16 '18 at 11:26