Hello I'm trying to Populate an Observable Collection through selected items of an Autocompletebox.
<Telerik:RadAutoCompleteBox Itemssource="{Binding People}" />
How should I initiate the Observable Collection to bind with RadAutocompleteBox.
And how should I set up SelectedItems binding method.
public class People
{
public string Person
{ get; set; }
public DateTime Date
{ get; set; }
}
public ObservableCollection<string> Persons{ get; set; }
You could try this to get the SelectedItems :
Add this to your viewmodel and edit your XAML.
ViewModel:
public ObservableCollection<People> SelectedPeoples { get; set; }
Xaml:
<Telerik:RadAutoCompleteBox Itemssource="{Binding People}"
SelectedItems="{Binding SelectedPeoples , Mode=TwoWay}"
SelectionMode="Multiple" />
After your edit
I see that you try to bind a class to the RadAutoCompleteBox rather than the ObservableCollection People, you have to bind the property Persons to the RadAutocompleteBox. This will bind the ObservableCollection to the RadAutoCompleteBox.
<Telerik:RadAutoCompleteBox Itemssource="{Binding Persons}" />
Also, you can edit the declaration of your ObservableCollection to
public ObservableCollection<People> Persons{ get; set; }
and edit the XAML like this:
<Telerik:RadAutoCompleteBox Itemssource="{Binding Persons}" DataMemberPath="Person" />
Your RadAutocompleteBox will now show the string Person declared in your People class.
If I'm looking at your code right, you are binding the items source to the class rather than to the collection. For an item's source binding to the collection is needed. You set the data context to the class.
Itemssource="{Binding Persons}"
Related
I have the following Models:
public class Profile
{
public string name { get; set; }
public Member casemanager { get; set; }
public Member assistant { get; set; }
}
public class Member
{
public int Id { get; set; }
public int Type{ get; set; }
public string Name { get; set; }
}
In my ViewModel, I have the following objects:
an ObservableCollection<Profile> named Profiles that gets populated from a database;
a SelectedProfile of type Profile, of course;
Two Lists of Members named ListCaseManagers and ListAssistants that get populated from DB.
Each of the objects implement a NotifyOfPropertyChange method from Caliburn.Micro and are set with property and backing field.
The View:
<StackPanel>
<ListView ItemsSource="{Binding Profiles}" SelectedItem="{Binding SelectedProfile}" DisplayMemberPath="name" SelectionMode="Single" />
<ComboBox ItemsSource="{Binding ListCaseManagers}" SelectedItem="{Binding SelectedProfile.casemanager }" IsSynchronizedWithCurrentItem="True" DisplayMemberPath="Name"/>
<ComboBox ItemsSource="{Binding ListAssistants}" SelectedItem="{Binding SelectedProfile.assistant}" IsSynchronizedWithCurrentItem="True" DisplayMemberPath="Name"/>
</StackPanel>
In this XAML I was thinking that the SelectedItem of each ComboBox would bind directly to the SelectedProfile casemanager/assistant, changing everytime I modify the SelectedProfile using the ListView, but it doesn't seem to select the item in the combobox even though SelectedProfile.casemanager and SelectedProfile.assistant are not null.
What am I missing? Is there an easy way using conventions with Caliburn.Micro?
In combobox present couple properties which can allow you to modify your SelectedItem in your list.
SelectedValuePath="Id" <br/>
SelectedValue="{Binding SelectedProfile.casemanager.Id}"
Upd: this approach allow to bind selected element by their some unique attribute (ID or Name)
In case if you need to work with SelectedItem.. you must sure that props of items in Profiles collection are related to object in ListCaseManagers and ListAssistants
var query = from p in Profiles
join mgr in ListCaseManagers on p.casemanager==mgr
select p;
? query.Count
enter code here
I assume you will see 0.. since objects in collection are different.
to use the convention name of Caliburn, you have to give a name to your control
for example for ListView:
<StackPanel>
<ListView x:Name ="Profiles" />
</StackPanel>
with the convention of names, Caliburn binds automatically the collection Profiles and use SelectedProfiles as SelectedItem
You either need to raise the PropertyChanged for the SelectedProfile property when it's set:
private Profile_selectedProfile;
public ProfileSelectedProfile
{
get { return _selectedProfile; }
set
{
_selectedProfile = value;
NotifyOfPropertyChange(() => SelectedProfile);
}
}
Or you could bind to the SelectedItem property of the ListView control itself:
<StackPanel>
<ListView x:Name="lv" ItemsSource="{Binding Profiles}"
SelectedItem="{Binding SelectedProfile}"
DisplayMemberPath="name" SelectionMode="Single" />
<ComboBox ItemsSource="{Binding ListCaseManagers}"
SelectedItem="{Binding SelectedItem.casemanager, ElementName=lv }"
DisplayMemberPath="Name"/>
<ComboBox ItemsSource="{Binding ListAssistants}"
SelectedItem="{Binding SelectedItem.assistant, ElementName=lv}"
DisplayMemberPath="Name"/>
</StackPanel>
I have a class defined like:
public class Agent
{
public int Id { get; set; }
public string Category { get; set; }
// rest removed for brevity
}
Then, in WPF, I get the data as List and pass it to DataContext as this:
List<Agent> agents; // this includes my data
this.DataContext = agents;
And in .xaml part I want to list the Category field of each object. I have something like this:
<ListBox
Name="agentCategoryListBox"
Grid.Row="2"
Grid.Column="1"
ItemSource="{Binding Path=Category"} />
But this doesn't seem to work correctly. Any ideas?
Let me help you to do this in the correct way as Alex suggested.
Create a list and populate it in ViewModel like this
ViewModel
public class MainWindowViewModel : INotifyPropertyChanged
{
public MainWindowViewModel()
{
agents = new ObservableCollection<Agent>();
LoadData();
}
private void LoadData()
{
agents.Add(new Agent { Id = 1, Category = "a" });
agents.Add(new Agent { Id = 2, Category = "b" });
agents.Add(new Agent { Id = 3, Category = "c" });
}
}
In XAML, Make your list and use data template like this:
<Window.Resources>
<DataTemplate x:Key="AItemTemplate">
<TextBlock Text="{Binding Category}"></TextBlock>
</DataTemplate>
</Window.Resources>
<ListBox ItemsSource="{Binding agents}"
ItemTemplate="{StaticResource AItemTemplate}"></ListBox>
That is it !!
Normally the DataContext would be a view model class that would contain the list of agents; then you can bind the ItemsSource to that list. Any of the many examples that deal with listbox will be pretty straight forward when it comes to that. Not really sure how the binding should look like if the list itself is the DataContext.
Then once the ItemsSource is set to a list of agents, if you want to show the Category in the list, the simpler way is to set DisplayMemberPath to "Category".
I suggest looking into MVVM and learning to apply it, it's an invaluable concept in my opinion.
You try to bind your listbox to a string property.
You can try this :
Give a name to your user control for exemle myUC
Add a property to your user control :
public List<Agent> AgentList { get; set; };
Fill your agentlist :
this.AgentList = //fill method
And bind your listbox like this :
<ListBox
Name="agentCategoryListBox"
Grid.Row="2"
Grid.Column="1"
ItemSource="{Binding Path=AgentList, ElementName=myUC"} />
may be this will give you an idea:
http://www.c-sharpcorner.com/forums/wpf-datacontext-binding-with-listbox
The fastest way to get what you want is :
<ListBox
Name="agentCategoryListBox"
Grid.Row="2"
DisplayMemberPath="Category"
Grid.Column="1"
ItemSource="{Binding Path=."} />
ItemsSource is binded directly to your Datacontext (which is your list) And then you tell to your ListBox to display the property Category.
But the proper way would have been :
1 - Create a DataContext
public class AgentsDC
{
public List<Agent> Agents { get; set; }
}
2 - Give this class as DataContext
this.DataContext = new AgentsDC();
3 - Bind all these things
<ListBox
Name="agentCategoryListBox"
Grid.Row="2"
DisplayMemberPath="Category"
Grid.Column="1"
ItemSource="{Binding Path=Agents"} />
I also would suggest you to use MVVM. But if you do not want to then try this.
XAML:
<ListBox Name="AgentCategoryListBox" ItemsSource="{Binding}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Category}" d:DataContext="{d:DesignData}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
CS:
public MainWindow()
{
InitializeComponent();
List<Agent> agents = new List<Agent>
{
new Agent
{
Category = "Category"
}
};
DataContext = agents;
}
public class Agent
{
public string Category
{
get;
set;
}
}
I am teaching myself how to bind classes to XAML objects. I can't find anything on data within lists. Either that or I don't know the terminology very well. I want to make a combobox that is tied to the list, displaying the name of each Item in the Items list. How would I bind this to the combobox?
class Section
{
List<Item> Items = new List<Item>();
}
class Item
{
private string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
}
Try This,
<ComboBox ItemsSource="{Binding Items}" DisplayMemberPath="Name" />
Make your Items collection as a property.
public List<Item> Items { get; set;}
Section Class should be public and make it as your DataContext
Assuming Section is the current DataContext :
<ComboBox ItemsSource="{Binding Items}"
DisplayMemberPath="Name" />
I have a viewmodel setup as the following
public class cDriveListVM
{
public string Drive { get; set; }
public cDriveListVM(string name)
{
Drive = name;
}
}
I declare the observablecollection in the window and set its datacontext to this observable collection.
public ObservableCollection<cDriveListVM> DriveList { get; set; }
private void dl()
{
DriveList = new ObservableCollection<cDriveListVM>();
DriveList.Add(new cDriveListVM("drive 1"));
DriveList.Add(new cDriveListVM("drive 2"));
this.DataContext = DriveList;
}
Xml for combobox:
<ComboBox x:Name="Drive_ComboBox" ItemsSource="{Binding Path=Drive}" HorizontalAlignment="Center" IsReadOnly="True" Grid.Column="0" Grid.Row="0" Width="300" Margin="10" SelectionChanged="Drive_Changed" Height="22" VerticalAlignment="Top"/>
I am just learning how to use Viewmodel so I am unsure what I am doing wrong, any help would be appreciated. I updated the xml file it results in the following combbox.
There are a few problems with this code.
One, the binding is set up wrong. Since the property with the viewmodel collection is DriveList, the binding should be ItemsSource="{Binding Path=DriveList}".
Two, you are attempting to display a field from your viewmodel, which is not doable. WPF's binding engine only works with properties, so the viewmodel should have a property:
public string Drive { get; set; }
And finally, the DisplayMemberPath should match the property name from the viewmodel: DisplayMemberPath="Drive".
Update: I just noticed that the DataContext is the observable collection itself -- I probably missed it on the first read. In that case, you want to bind directly to the data context:
ItemsSource="{Binding}"
And set DisplayMemberPath to the property you want to display:
DisplayMemberPath="Drive"
In WPF, I'm trying to bind multiple controls, but the second control isn't changing when the first control is changed.
I have two classes: a Task class, and a Log class, which is stored as a collection in the Task class. The list boxes below are bound to the Tasks, and the inner Logs for the selected Task.
The problem is that the list boxes are populated fine at first load, but if I select a different task, I'd expect the Logs to be update to the collection for the new Task, but it doesn't change from those from the originally selected task on first load. What am I missing?
In the designer:
<ListBox x:Name="listBoxTasks" ItemsSource="{Binding}" DisplayMemberPath="Key"
Grid.Row="0" Grid.Column="0" Grid.RowSpan="2">
</ListBox>
<ListBox x:Name="listBoxLogs"
ItemsSource="{Binding Logs}" DisplayMemberPath="EntryDate"
Grid.Row="1" Grid.Column="1">
</ListBox>
In the code behind:
public MainWindow()
{
InitializeComponent();
IMongoCollection<Task> tasks = DataManager.GetData();
this.DataContext = tasks.AsQueryable();
}
The Task class:
public class Task : BusinessBase<Task>
{
public ObjectId _Id { get; set; }
public string Key { get; set; }
public string Description { get; set; }
public string Summary { get; set; }
public string Details { get; set; }
public IEnumerable<Log> Logs { get; set; }
public IEnumerable<Link> Links { get; set; }
public IEnumerable<String> RelatedKeys { get; set; }
public IEnumerable<TaskItem> Items { get; set; }
}
Your Task class need to implement INotifyPropertyChanged interface so that as soon as there is any change in the underlying data it can tell WPF UI that something has changed now update/refresh your controls agains
Your task class need to implement INotifyPropertyChanged
http://msdn.microsoft.com/en-us/library/ms743695.aspx
You have to bind your first ListBox SelectedItem to object of Task model and add event handler for SelectionChanged. inside the this event you have to populate your logs by selected Task model also you have to implement INotifyPropertyChanged in your class.
It looks to me like the second binding should not work at all, as the DataContext is an enumerable of Tasks and the enumerable itself has no property called Logs. You could try working with IsSynchronizedWithCurrentItem and a binding to the current item:
<ListBox x:Name="listBoxTasks" ItemsSource="{Binding}" DisplayMemberPath="Key"
Grid.Row="0" Grid.Column="0" Grid.RowSpan="2"
IsSynchronizedWithCurrentItem="True"> <!-- Set this -->
</ListBox>
<ListBox x:Name="listBoxLogs" DisplayMemberPath="EntryDate"
Grid.Row="1" Grid.Column="1"
ItemsSource="{Binding /Logs}"> <!-- Note the slash which indicates a binding to the current item -->
</ListBox>
You could also bind to the SelectedItem of the other ListBox but this introduces a redundant dependency between the controls. Also note that if you change any property in your data-objects you need to implement the interface mentioned by the other answerers, INotifyPropertyChanged.
I have it all working now. I implemented INotifyPropertyChanged, although that didn't solve the problem.
I am now using the MVVM pattern. This helped...the NoRM library I was using didn't have a SelectionChanged event. I created a View Model and was able to convert those Models to ObservableCollections. Now I'm just setting the Logs control DataContext on selection changed for the Task class.