Data-Binding: Right way to update ObservableCollection
I'm playing around with the data-binding examples.
https://www.noesisengine.com/docs/Gui.C ... orial.html
I successfully tested the "Binding to a Collection" example.
But what's not covered there, is how I can update this particular ObservableCollection to automatically synchronize and add a player in the ListBox.
The tutorial says, ObservableCollection updates itself, but I can't confirm that... Once the ListBox is initially filled, I am unable to modify it any further.
What do I have to do to add an additional Player entry into the ListBox in the tutorial to a later point?
https://www.noesisengine.com/docs/Gui.C ... orial.html
I successfully tested the "Binding to a Collection" example.
But what's not covered there, is how I can update this particular ObservableCollection to automatically synchronize and add a player in the ListBox.
The tutorial says, ObservableCollection updates itself, but I can't confirm that... Once the ListBox is initially filled, I am unable to modify it any further.
What do I have to do to add an additional Player entry into the ListBox in the tutorial to a later point?
-
sfernandez
Site Admin
- Posts: 3152
- Joined:
Re: Data-Binding: Right way to update ObservableCollection
I suppose you are setting the ObservableCollection in the ListBox.ItemsSource property. And you defined an appropriate DataTemplate in the ListBox.ItemTemplate property (or used DisplayMemberPath property instead). Once you do that, adding/removing to/from the collection should update the ListBox automatically, there is no need to do anything manually.
Code: Select all
<ListBox ItemsSource="{Binding Players}" DisplayMemberPath="Name"/>
Code: Select all
public class Player
{
public string Name { get; set; }
}
public class ViewModel
{
public ObservableCollection<Player> Players { get; private set; }
public ViewModel() { Players = new ObservableCollection<Player>(); }
}
...
void OnAddPlayer(string name)
{
ViewModel vm = ...;
vm.Players.Add(new Player { Name = name });
}
void OnRemovePlayer(Player player)
{
ViewModel vm = ...;
vm.Players.Remove(player);
}
Re: Data-Binding: Right way to update ObservableCollection
But to access the Players property of the ViewModel class, I can only instantiate a new object and can't access the "original" Players collection (?).
I guess I'm having a huge understanding problem here:
To not leave anything out, this is the xml (unchanged from the tutorial):
The classes are also unchanged:
Now what can I do in my code to update the List?
In your example you left out the (for me) important part:
I tried this:
Nothing happens...
I guess I'm having a huge understanding problem here:
To not leave anything out, this is the xml (unchanged from the tutorial):
Code: Select all
<Grid
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="600">
<Grid.Resources>
<DataModel3 x:Name="dataModel" />
<DataTemplate x:Key="TaskTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="200"/>
</Grid.ColumnDefinitions>
<Rectangle Width="15" Height="10" Fill="{Binding Color}" Stroke="Transparent" StrokeThickness="0"
Margin="5, 0, 5, 0" Grid.Column="0"/>
<TextBlock Text="{Binding Name}" Margin="5, 0, 5, 0" Grid.Column="1"/>
<TextBlock Text="{Binding Scale, StringFormat=P0}" Margin="5, 0, 5, 0" Grid.Column="2"/>
<TextBlock Text="{Binding Pos}" Margin="5, 0, 5, 0" Grid.Column="3"/>
</Grid>
</DataTemplate>
</Grid.Resources>
<ListBox Height="100" DataContext="{StaticResource dataModel}"
ItemsSource="{Binding Players}"
ItemTemplate="{StaticResource TaskTemplate}" />
</Grid>
Code: Select all
public class Player
{
public Player(string name, Noesis.Color color, float scale, string pos)
{
Name = name;
Color = new SolidColorBrush(color);
Scale = scale;
Pos = pos;
}
public string Name { get; private set; }
public Brush Color { get; private set; }
public float Scale { get; private set; }
public string Pos { get; private set; }
}
public class DataModel3
{
public DataModel3()
{
Players = new ObservableCollection<Player>();
Players.Add(new Player("Player0", Colors.Red, 1.0f, "(0,0,0)"));
Players.Add(new Player("Player1", Colors.Gray, 0.75f, "(0,30,0)"));
Players.Add(new Player("Player2", Colors.Orange, 0.50f, "(0,-10,0)"));
Players.Add(new Player("Player3", Colors.Green, 0.85f, "(0,-10,0)"));
}
public ObservableCollection<Player> Players { get; private set; }
}
In your example you left out the (for me) important part:
What do I have to write for "..."?ViewModel vm = ...;
vm.Players.Add(new Player { Name = name });
I tried this:
Code: Select all
public void AddPlayer()
{
Debug.Log("AddPlayer button clicked");
DataModel3 dm = new DataModel3();
dm.Players.Add(new Player("Player4", Colors.Yellow, 3.0f, "(5,0,0)"));
}
- ai_enabled
- Posts: 231
- Joined:
- Contact:
Re: Data-Binding: Right way to update ObservableCollection
Hansi, sorry for maybe being rude, but are you a novice programmer? You need a basic knowledge of OOP if you want to develop something with NoesisGUI. The tutorials are actually very straightforward if you know OOP and have some programming experience. Just keep this in mind.
Let's see what's the issue here:
You create a new instance of DataModel3 class and and a new player to its Players collection... It will not work as your XAML view is bound to another DataModel3 instance.
Find the code where you create the new DataModel3 for the first time and save this created instance in a field. Then you need to use this field to add the new player to the collection. Do not create new DataModel3, use the existing one from the field. I hope it helps.
Let's see what's the issue here:
Code: Select all
public void AddPlayer()
{
Debug.Log("AddPlayer button clicked");
DataModel3 dm = new DataModel3();
dm.Players.Add(new Player("Player4", Colors.Yellow, 3.0f, "(5,0,0)"));
}
Find the code where you create the new DataModel3 for the first time and save this created instance in a field. Then you need to use this field to add the new player to the collection. Do not create new DataModel3, use the existing one from the field. I hope it helps.
AtomicTorch Studio Pte. Ltd. http://atomictorch.com
Re: Data-Binding: Right way to update ObservableCollection
No worries, yes I am a novice programmer
But thank you for helping me out, anyway.
That's what I thought, but desperation made me try these things.
That's because my question is (like I said in my last post): How can I find the "original" object, because there is none created in the tutorial.
It's just the initial constructor of DataModel3 which creates the Players Collection.
Again, there has no object been created explicitly by me. So how do I access this collection, when there is no existing object?
But thank you for helping me out, anyway.
That's what I thought, but desperation made me try these things.
That's because my question is (like I said in my last post): How can I find the "original" object, because there is none created in the tutorial.
It's just the initial constructor of DataModel3 which creates the Players Collection.
Again, there has no object been created explicitly by me. So how do I access this collection, when there is no existing object?
- ai_enabled
- Posts: 231
- Joined:
- Contact:
Re: Data-Binding: Right way to update ObservableCollection
Hansi, I checked the tutorial code for this example and I can agree it's not really straightforward here, even for non-novice programmers . You can't access this data object easily as it's defined as a static resource. It was done on purpose to demonstrate how the data binding for collections works, but it's a bad example as it's hard to do the collection modification.
The common approach is to create a view model class instance (in that case, DataModel3) in the codebehind of the UserControl, then assign it to some field and this.DataContext property.
Then in XAML you can bind to properties of this view model instance. When you need to modify something in your view model instance, you can access it through the field.
Alas, I can't find any good tutorial for it there https://www.noesisengine.com/docs/Gui.Core.Index.html (Unity UserControl sample here is so complicated!) or on Github... so perhaps NoesisGUI team will create a new, really straightforward sample to demonstrate this approach.
The common approach is to create a view model class instance (in that case, DataModel3) in the codebehind of the UserControl, then assign it to some field and this.DataContext property.
Then in XAML you can bind to properties of this view model instance. When you need to modify something in your view model instance, you can access it through the field.
Alas, I can't find any good tutorial for it there https://www.noesisengine.com/docs/Gui.Core.Index.html (Unity UserControl sample here is so complicated!) or on Github... so perhaps NoesisGUI team will create a new, really straightforward sample to demonstrate this approach.
AtomicTorch Studio Pte. Ltd. http://atomictorch.com
Re: Data-Binding: Right way to update ObservableCollection
Thank you very much for your dedication, ai_enabled!
ListBox.DataContext did the trick!
I wanted to try that approach some time ago, but I was so stuck on the tutorial template code that i never went the obvious way...
An updated tutorial doesn't sound like a bad idea, I agree. It doesn't prepare for the full data-binding potential
ListBox.DataContext did the trick!
I wanted to try that approach some time ago, but I was so stuck on the tutorial template code that i never went the obvious way...
An updated tutorial doesn't sound like a bad idea, I agree. It doesn't prepare for the full data-binding potential
-
sfernandez
Site Admin
- Posts: 3152
- Joined:
Re: Data-Binding: Right way to update ObservableCollection
Trying to put in code what aienabled was talking about, in case is useful for others:
Having a xaml like this:
The code-behind (and related classes) would look something like this:
Hope this helps.
Having a xaml like this:
Code: Select all
<UserControl x:Class="PlayersList"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
...
<ListBox ItemsSource="{Binding Players}" DisplayMemberPath="Name"/>
...
</UserControl>
Code: Select all
public class Player
{
public string Name { get; set; }
...
}
public class PlayersListVM
{
public PlayersListVM() { Players = new ObservableCollection<Player>(); }
public ObservableCollection<Player> Players { get; private set; }
...
}
public class PlayersList : Noesis.UserControl
{
private PlayersListVM playersListVM;
public PlayersList()
{
InitializeComponent();
playersListVM = new PlayersListVM();
DataContext = playersListVM;
}
private void InitializeComponent()
{
Noesis.GUI.LoadComponent(this, "...path_to_PlayersList.xaml....");
}
void OnAddPlayer(string name)
{
playersListVM.Players.Add(new Player { Name = name });
}
void OnRemovePlayer(Player player)
{
playersListVM.Players.Remove(player);
}
...
}
Re: Data-Binding: Right way to update ObservableCollection
Now that we are working in the new application framework, all examples are being improved. Thanks for this feedback!
Who is online
Users browsing this forum: Ahrefs [Bot], Bing [Bot] and 0 guests