WPF/VC++ (C++/cx) - Visual Studio 2013
So I have a ListBox thats populated with a UserControl I\'ve created. Every time the page changes the data is lost, which is
Without any more background information, nor details about what you're doing (since you can't post any code or screenshots), I can only tell you what's the basic idea behind The WPF Mentality.
WPF is really different from pretty much any other UI frameworks I've heard of, in the sense that it is really intended to be used for Data-Centric development.
From the ground up, WPF is largely based on DataBinding. This eliminates in like 95% the need to do any manipulations of the UI via procedural code.
As a simple example, say you have a Person
class which contains string LastName
and string FirstName
properties:
public class Person
{
public string LastName {get;set;}
public string FirstName {get;set;}
}
Instead of passing data values back and forth to the UI by writing procedural code-behind like this:
//Traditional approach, Don't use this in WPF.
this.txtLastName.Text = person.LastName;
this.txtFirstName.Text = person.FirstName;
//...
person.LastName = this.txtLastName.Text;
person.FirstName = this.txtFirstName.Text;
you simply define a DataBinding in XAML, declaratively:
<TextBox Text="{Binding LastName}"/>
<TextBox Text="{Binding FirstName}"/>
and then set the UI's DataContext to a relevant instance of data:
//Window constructor example
public MainWindow()
{
InitializeComponent();
DataContext = new Person();
}
This approach has the following advantages:
Data <=> UI
).TextBox.TextChanged
event. WPF takes care of passing the Text
value from the TextBoxes in the example to the underlying Data Object when needed.With ListBox
es, ComboBox
es, Menu
s, TabControl
s, DataGrid
s, and ALL ItemsControls it's exactly the same:
You don't "populate a ListBox with UserControls", instead:
you create a proper ViewModel which contains an IEnumerable<T>
which holds your data items. The ObservableCollection<T> is preferred because WPF listens to it's CollectionChanged
event and updates the UI accordingly when items are added/removed from the collection:
public class MyViewModel
{
public ObservableCollection<Person> People {get;set;}
//Constructor
public MyViewModel()
{
People = new ObservableCollection<Person>();
//populate the collection here...
}
}
Then you Define the ListBox In XAML and use WPF's Data Templating capabilities to Define how the UI will look like for each item:
<ListBox ItemsSource="{Binding People}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBox Text="{Binding LastName}"/>
<TextBox Text="{Binding FirstName}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Note: It's the same if you want to use a UserControl
in there instead:
<DataTemplate>
<my:MyUserControl/>
</DataTemplate>
And finally set the UI's DataContext to an instance of the ViewModel:
//Window Constructor
public MainWindow()
{
InitializeComponent();
DataContext = new MyViewModel();
}
Note: I mentioned the INotifyPropertyChanged interface in the comments. this interface must be implemented by your Data Items or ViewModels in order to support Two-way Binding properly. Otherwise WPF has no way to "know" when a specific property (such as
LastName
) is changed and update the UI accordingly. I consider that topic to be out of the scope of this answer and therefore I won't get into it. You can read the linked material, and there is also plenty of material in the Web about it.
As I already mentioned, I have no experience at all in C++, therefore all these examples are in C#. Remember I also mentioned WPF only supports databinding to .Net Objects, and I don't think it supports lower-level in-memory structures such as the ones you may construct in C++.
My suggestion is that you use C# for the upper-level UI-facing part of your software, while leaving C++ for any lower-level operations you might need.
I strongly suggest reading thru the material linked in this post, most importantly Rachel's WPF Mentality and the ItemsControl-related material.