Instance of Object to bind and manipulate it? - c#

I want to display an instance that the user can select by using a combobox. The combobox get all entries from a ObservableCollection<string> Names {get;set;} with a binding.
What is the best way to display all properties of this instance with a binding?
My idea was to create a ObservableCollection<Foo> Bar {get;set;}.
Now the user choosed on entry inside the combobox.
With the selected name I will search the instance with this name in ObservableCollection<Foo> Bar {get;set;} and copy it into a new instance Foo TMPBar {get;set;}.
And this instance should be binded to the GUI.
Is that a good solution way?

Rather than bind the combo box to a list of names, bind to a list of the actual objects and use the DisplayMemberPath property of the ComboBox to just show the name.
Then you've got direct access to the the object via the SelectedItem property.
So you'll need:
public ObservableCollection<Foo> Bar { get; set; }
public Foo Selected { get; set; }
in your view model, and:
<ComoboBox ItemsSource="{Binding Bar}"
DisplayMemberPath=Name
SelectedItem="{Binding Selected}" />
in your view.

Related

WF .Net ComboBox Control - How to show only items that match a condition

I have a BindingList list and a ComboBox dropdownUI.
If I do: dropdownUI.DataSource = list, all the employees in the list will show in the drop down. I want to know if there is a way to only show the employees that have hidden = false so when I modify the employee hidden attribute, I can hide the record from the combo box?
public class Employee {
public string name {get; set;}
public bool hidden {get; set;}
public Employee(string name, bool hidden) {
this.name = name;
this.hidden = hidden;
}
}
There is no way using the BindingList itself. It implements the IBindingList interface but you need the IBindingListView interface to get filtering. You have three main options:
Define your own custom class that implements IBindingListView.
Populate a DataTable with the data and either bind that directly or bind it via a BindingSource. When you bind a DataTable, the data actually comes from its DefaultView, which is type DataView. Both DataView and BindingSource implement IBindingListView.
Create a new list based on the desired filter and bind that instead of the original list.
The first two options would allow you to modify an item and have the filter automatically update the UI, while the third option would require you to generate a new filtered list every time you modify an item.

Siverlight: DataGridView adding items and getting selected items

I use the DataTable for adding items to a DataGridView and the DataGridRow for getting the select items out of it in WPF but the silverlight appears not to have those types. I would like to know what the appropriate way is to add data and get them back to and from the DataGridView in silverlight since those things are not available in this framework.
You don't need to bind your data with the data grid view like that at all. (By using DataTable). Instead you you can make a list of your models and directly bind it to the item source of the grid view. For example:
// Example Model
public class MyModel{
public int Id {get; set;}
public String Title {get; set;
}
List<MyModel> MyList = new List<MyModel>(){ new MyModel{ Id = 1, Title = "Jack"}};
MyDataGridView.ItemSource = MyList;
And to get the selected row you can:
var Row = (MyModel) MyDataGridView.SelectedItem;

Bind object properties to a datagrid in WPF

I have the following class:
public class Sp3dItem
{
public Sp3dItem()
{
Items= new ObservableCollection<Sp3dItem>();
}
public string OID
{
get;
set;
}
public string Name
{
get;
set;
}
public string Type
{
get;
set;
}
public ObservableCollection<Sp3dItem> Items
{
get;
set;
}
}
I need to show the properties of an instance of this object to a Datagrid (or any other type of grid). Like the Properties Window in Visual Studio. But there are certain properties that I don't care, like 'Items', I only need to show properties of string Type, and only the ones with non empty values (this last one would be a plus, not a real need).
The question is, can I do something like this with binding or do I have to assembly the data on the grid manually?
Sounds like you want a property grid to view the properties of a single object instance, where each property/value pair is a 'row', yes? If that's the case, look into some of the third-party Property Grid controls. The WPF Extended Toolkit has a free one.
Typically, these grids can automatically discover the properties of the target object, and you can choose to hide certain properties by adorning them with [Browsable(false)].
Yes... it's possible and easy once you figure out how the built-in binding wizard works.
This example is for a
<Label...
Create a static instance to your view model in the View. By doing this the designer will show the properties of the Viewmodel in the
properties page once you start "wiring up the bindings"...
//in code behind
public static string Error
{
get { return _Error; }
set { _Error = value; }
}
Now click on the XMAL component in designer just once.
<Label Grid.Row="2" <=Click here one time
In the properties page, click the icon (small square on far right side of property) to start the binding process
Select "Create Data Binding"
Select 'FindAncestor' then the MainWindow of interest, and finally the static property.
Click ok and the bindings are set in XAML Automatically.
<Label Grid.Row="2"
Content="{
Binding Error,
RelativeSource={
RelativeSource FindAncestor,
AncestorType={x:Type local:MainWindow}}}"/>
The verbosity above just says:
Look in MainWindow's static properties for Error.
Make this Label's content that value.
If you want you can also edit the template for the Datagrid, but that's not relevant to your question.

How to bind to a ComboBox in WPF with Data and Value pointing to 2 properties

I have a class with similar structure as given below:-
public class Sample
{
public List<string> Names { get; private set; }
public List<int> IDs { get; private set; }
// Some logic to populate these collections.
}
Now in another XAML file, I need to bind Names property to a ComboBox and based on the selection I need to get the corresponding ID as selected value. Is there way I can solve this problem using binding?
I have an object of Sample class in my model like below:-
public class Model
{
public Sample Object
{
get { return _sample; }
set { _sample = value; }
}
}
I'm not allowed to change the Sample entity class. Please guide me on how to solve this problem.
You need to merge the two different lists into a single list of an object with two values before binding, fortunately doing so is rather straightforward, just use Zip:
var data = sample.Names.Zip(sample.IDs, (name, id)=> new{name, id});
Then bind to data as you normally would.
Your best bet is to wrap the Name and ID into a separate class, then bind the ItemsSource to the collection of Name/ID pairs. Set the DisplayMemberPath on the ComboBox to "Name".
On the View Model, you can have a property for the selected Name/ID pair, or just the selected ID. If you want to do the latter, just set SelectedValuePath to "ID" and bind SelectedValue to the ID property on your view model (note that if you do it this way, you can use the anonymous class projection from Servy's answer). Otherwise, just bind SelectedItem to your selected Name/ID pair property (this version requires a named class).

Swapping the binding on a ListBox when selecting a ViewModel in a List of ViewModels in Caliburn Micro?

I have a list of ViewModels each of which contains a list.
I want to bind this list to a ListBox in the view, so that I can set a SelectedViewModel and the ListBox in the view now shows the entries in the new SelectedViewModel. This should also preserve selection.
Is it possible to do this with the current Caliburn Micro conventions or do I have to explicitly state this?
For example:
I have a list of ViewModels called vmList containing two ViewModels, Fruit and Veg.
The ViewModel Fruit contains the list ["Apple", "Pear"].
The ViewModel Veg contains the list ["Carrot", "Cabbage"].
Fruit is the current SelectedViewModel so my view's ListBox currently should show:
Apple
*Pear*
Pear is currently the selected item in the ListBox.
Now I set Veg as the SelectedViewModel and my View updates to show:
*Carrot*
Cabbage
Carrot is currently the selected item in the ListBox.
Now if I set Fruit back to being the SelectedViewModel my View should update to show:
Apple
*Pear*
Where Pear is still the selected item in the ListBox.
This should be possible - the simplest functionality for this would be using CMs conventions to bind the list content, and also supplying a SelectedItem binding for the list. Since you want to track the last selected item in each VM, you need to keep tabs on that too (either in the VMs themselves or in the main VM)
So the solution could be:
public class ViewModelThatHostsTheListViewModel
{
// All these properties should have property changed notification, I'm just leaving it out for the example
public PropertyChangedBase SelectedViewModel { get; set; }
public object SelectedItem { get; set; }
// Dictionary to hold last selected item for each VM - you might actually want to track this in the child VMs but this is just one way to do it
public Dictionary<PropertyChangedBase, object> _lastSelectedItem = new Dictionary..etc()
// Keep the dictionary of last selected item up to date when the selected item changes
public override void NotifyOfPropertyChange(string propertyName)
{
if(propertyName == "SelectedItem")
{
if(_lastSelectedItem.ContainsKey(SelectedViewModel))
_lastSelectedItem[SelectedViewModel] = SelectedItem;
else
_lastSelectedItem.Add(SelectedViewModel, SelectedItem);
}
}
}
Then in your XAML
<ListBox x:Name="SelectedViewModel" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" />
Obviously set your item template here to bind to a common property on the viewmodels (such as DisplayName using IHaveDisplayName interface to keep things nice and integrated)
Edit:
Just a quick note: if your VMs themselves aren't List objects and instead contain a list, then you might have to bind the list items explicitly to the ListBox but it depends on your ItemTemplate (you can get CM to keep resolving VMs and Views for VMs based on ContentControl convention bindings)
<ListBox ItemsSource="{Binding SelectedViewModel.ListItems}" ...etc />

Categories

Resources