WPF Listbox Items - wpf

I have a ListBox control that contains the names of files inside a directory.
How would I iterate though the controls and get those names? I've tried:
for (int i = 0; i < listboxFileGroups.Items.Count; i++)
{
// I don't want to use properties that start with Selected
// Here is what I was looking for
string textItem = listboxFileGroups.Items[i].ToString();
}
Any suggestions?

You may want to explore an MVVM approach.
In one of your view model classes, you can have an ObservableCollection<string>:
public ObservableCollection<string> StuffForListBox { get; set; }
Populate that ObservableCollection with what you want to get displayed in the ListBox.
In the code-behind of the UserControl or Window in which you have the ListBox, set the DataContext to an instance of the class containing StuffForListBox seen above.
this.DataContext = new MyClass();
Alternatively you could also create a datatemplate for the usercontrol / window which will automagically wire up the datacontext with your view model.
Since you only mentioned that you want to display the files in a directory (not including sub-directories), you just need to bind the ItemsSource to StuffForListBox.
<ListBox ItemsSource="{Binding StuffForListBox}" ... >
To iterate through the strings displayed in the ListBox you just need to iterate through the ObservableCollection.
If you don't want to bother with MVVM or if that is some third party listbox, you can try grabbing the ItemsSource in the codebehind and loop through that but I'd certainly recommend MVVM. It'll make your life easier.
Now, if you wanted to get a little crazier and display things like subfolders then an ObservableCollection<string> won't cut it. You would need to create a class that contains children to model how a folder has files and subfolders.
public class DemoItem
{
public string Name { get; set; }
public DemoItem Parent { get; set; }
public ObservableCollection<DemoItem> Children { get; set; }
public bool IsSelected { get; set; }
}
...and then base your observable collection thats bound to the listbox on the above class.
If and when you do that, your listbox won't display the items properly until you create a DataTemplate But I suppose that't outside of the scope of the question :p

Related

WPF: Binding listview itemsource from viewmodel in MVVM [duplicate]

This question already has an answer here:
Creating and binding buttons dynamically in a WrapPanel
(1 answer)
Closed 5 years ago.
I am trying to set ItemSource property for listview without success.
View (xaml):
<ListView Margin="10" Name="MyLv" ItemsSource="{Binding}">
....
</ListView>
Code-Behind Constructor (xaml.cs):
public MyView()
{
InitializeComponent();
}
ViewModel:
private List<DataModel> lstData = null;
public MyViewModel()
{
this.lstData = this.LoadData(); // this connects to a database an extract info to be loaded in listview
}
Data Model:
public class DataModel
{
public bool IsSelected { get; set; }
public string ID { get; set; }
public string Desc { get; set; }
}
Before this, I was loading the listview from code-behind and it was working, but now I want to load it from my viewmodel and I do not know how can I make it work.
Based on the code you posted, there are a couple of problems:
You haven't set the DataContext of the view. You typically want to set this to an instance of your view model class.
The ViewModel doesn't expose the list as a public property. WPF bindings only work on public properties. The ItemsSource should be bound to this property, and not to the DataContext itself.
Finally, you probably want the collection in the ViewModel to be an ObservableCollection. This way, when changes are made to the collection, the list in the UI will be automatically updated.

Binding to a property of the DataContext of another control

iv'e got 2 panels in an app game
they are both bound to different elements .
GameDetailsPanel.DataContext = game ;
GameBoardPanel.DataContext = gameBoard ;
*Game has a Turn Property * .
public Class Game
{
public bool Turn{ get; set;}
}
now i need to bind one of GameBoardPanel to the value of the Property Turn ,
*for example : something along the lines of *
<Button Fill={Binding Source=GameDetailsPanel.DataContext , Path=Turn } ></Button>
how can i reference GameDetailsPanel.DataContext in my binding ?
For the benefit of searchers, you can bind to the datacontext of another control as detailed here.
The quick solution in my case looked like:
<TextBlock Text="{Binding ElementName=ucClientDetails,
Path=DataContext.FullName}"></TextBlock>
where 'ucClientDetails' was a user control bound to a viewmodel containing client details (including FullName).
I would recommend having your game and gameBoard properties on a wrapper view model and then setting the datacontext of your view to the wrapper view model. That way in your button's Fill binding you could simply reference the appropriate property on your view model:
public Class Wrapper_ViewModel
{
public Game game{ get; set; }
public T gameBoard{ get; set; }
}
<Button Fill={Binding Path=game.Turn} ></Button>
However, for more one-off scenarios you could use the relative source binding attribute and hook another elements data context, as in this example:
Access parent DataContext from DataTemplate
use simply
<Button Fill="{Binding ElementName=GameDetailsPanel,Path=DataContext.Turn}"></Button>
this element binding.

Binding ContextMenu on flattened ViewModel

suppose the following classes:
public class Model
{
public ObservableCollection<A> Items { get; set; }
}
public class A
{
ObservableCollection<B> Data { get; set; }
//... some more properties
}
public class B
{
//..properties
}
The model is bound to a RibbonMenu and should also be used in a context menu. The context menu must be bound to all items of class B in the model. Changes in the model (new items added, items removed, items changed ...) should change both the context menu and the RibbonMenu.
The RibbonMenu works nicely but how is it possible to bind the contextmenu without creating a separate model?
You could create wrapper properties that flatten your A and B entities as needed for the view controls and expose them publicly from Model.
So, for instance, in Model, you have a private backer of ObservableCollection<A>. Then you have a public ObservableCollection<A> that simply returns the private backer for the ribbon to bind to.
Then also have a public ObservableCollection<B> that does whatever it needs to do in its getter to return what you want for the context menu. For example, if you want the distinct Bs across all As, have the getter do a query on all of A's Bs to return the correct list.
Finally, to tell the view that changes were made in Model, implement INotifyPropertyChanged and raise the PropertyChanged event in the setters of your public members.

Bind a WPF data grid to multiple data sources

I have created a data grid in WPF and have 2 lists. I want to bind one column to one list and rest of the columns to another list.
Can anyone please tell me how to do this?
Thanks
Basically, You cant. The datagrid is an ItemsControl which has one ItemsSource property.
What i would do is build a view model which is a composite object that contains one of each of the items (from the two lists). then you could bind to a collection of these.
public class CompositeItem{
public Object ItemFromListOne { get; set; }
public Object ItemFromListTwo { get; set; }
}

How to bind WPF Datagrid itemssource to Collection of Collections?

What is the best approach to bind a WPF DataGrid ItemsSource to an ObservableCollection of ObservableCollections ?
e.g.
public ObservableCollection<ObservableCollection<MyDataItem>> DataValues = new ObservableCollection<ObservableCollection<MyDataItem>>();
where MyDataItem may look like this:
public class MyDataItem
{
public string Caption { get; set; }
public string DataValue { get; set; }
}
I can assume the collection of collections isn't jagged, and they all contain the same number of "columns"
Is it possible to bind each column dynamically to the 'DataValue' property of the MyDataItem objects or do I need to pack the data into an easier structure to bind to?
This is possible by using a collection-derived class as the inner object, and implementing ICustomTypeDescriptor on it - See a similar SO question on the topic (tagged with Silverlight, but same idea)
Silverlight DataGrid - Binding to a Collection of Collections of objects.

Resources