I have a list box bound to a collection, PlaylistTracks. PlaylistTracks contains a list id and a track id. All tracks are stored in another collection, Tracks. This collection has the track name.
Can I get the list box to display the track name from the collection its not bound to? Something like this:
<ListBox Name="PlayListTracksBox"
ItemsSource="{Binding Path=PlaylistTracks, Mode=TwoWay}"
DisplayMemberPath="Tracks.Name"
SelectedItem="{Binding Path=SelectedListTrack, Mode=TwoWay}"></ListBox>
I believe overriding ToString() for whatever class PlaylistTracks contains would be the fastest way to get what you want to work. Inside of ToString you'd have to put whatever logic you need to look up the correct track, and return the name therefrom.
If you can get the track name into the top-level object in your ItemsSource, then the more "Silverlighty" way to get this to work is to provide an ItemTemplate and bind to whatever you want. Something like:
<ListBox>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Tracks.Name}"></TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Related
I have a datagrid of rows which contain data read from a web server and values I want to write into a webserver. I write the values in getting the user to input a number into the appropriate column and click an adjacent text box;
<DataGrid x:Name="datagridDERControl" HorizontalAlignment="Center" VerticalAlignment="Center" Background="#FF322D2D" Height="382" Margin="10,78,10,10" Width="972" ItemsSource="{Binding Path=NFDataSource, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<DataGrid.Columns>
<DataGridTemplateColumn Width="100" Header="Write Set Point">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox Width="100" Text="{Binding Path=WriteSetPoint, Mode=OneWayToSource, UpdateSourceTrigger=PropertyChanged}"></TextBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Width="100" Header="Global Trip">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Name="buttonGlobalTrip" Width="100" Click="buttonGlobalTrip_Click"></Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid
How do I extract the specific textbox string per row to use in my view model.
It's always difficult to answer a question where the relevant details have been omitted by the question author. However, I shall try!
You have data bound (presumably) a collection property named NFDataSource to your DataGrid.ItemsSource property. That is the collection that represents the data in your DataGrid, so to 'extract' a specific value, you need to look into your data items in your collection.
One handy property in the DataGrid class is the SelectedItem property. this enables you to data bind an object (of the same type as those in your NFDataSource collection) to this property, which accesses the data object behind the row that is currently selected in the UI:
<DataGrid ItemsSource="{Binding NFDataSource}" SelectedItem="{Binding SelectedItem}" />
Now you can utilise your SelectedItem property to access the values from the selected row in the DataGrid:
string someValue = SelectedItem.SomeProperty;
As you tagged this with MVVM and databinding, I'll assume you're using these and have just got muddled.
"I have a datagrid of rows which contain data read from a web server
and values I want to write into a webserver."
So your viewmodel has a property, which is a collection of a custom class, that represents data fetched from a webservers.
"I write the values in getting the user to input a number into the
appropriate column and click an adjacent text box"
So this VM property is two-way bound to a datagrid, so that each item in the collection represents 'one row', and the properties on those items represent your 'columns'. The user can make changes to the UI displayed values, and because of the two way databinding the VM property is also updated.
"How do I extract the specific textbox string per row to use in my
view model."
Why do you need the specific textbox string, if it is databound to a property (or rather to a property on a class contained in a collection) in your VM anyway? If you've set up your VM this way, and are using databinding, you rarely need to worry about UI specific things such as which row in a datagrid is clicked.
As Sheridan points out though, you can also bind to properties on the datagrid such as SelectedItem so that you can perform additional operations beyond just reading/writing data. SelectedItem for your datagrid will be of the type that populates your VM collection, so will have the appropriate properties.
For example, if your VM collection is an IQueryable<Person> and that is bound to the ItemsSource of the datagrid then the SelectedItem will be of type Person. You could then have a VM property called SelectedPerson which is bound to that SelectedItem, and access things like SelectedPerson.Name etc.
I want to create a ListBox and fill it with anonymous UIElement. In other words, the DataTemplate of the ItemTemplate will contain only one element, and afterwords during the runtime, afterwards I will create in the code behind different UIElements (TextBlocks, Grids ...) and populate the list with it.
So how am I going to write the DataTemplate of the ListBox? And how am I intend to use an ObservableCollection for the ItemSource? So should use an ObsevableCollection of UIElement?
First Question: No DataTemplate. Since your items are already UIElements, you don't need a DataTemplate.
And if you're creating a changeable collection, then yes, ObservableCollection<UIElement> is the way to go.
Now, why would you be doing this? You may want to ask yourself if this is the best way of doing things. Why isn't your data and your presentation separated? If you need more than one type of element in the list, will DataTemplateSelector allow you to have a real ViewModel?
<ListBox x:Name="name" ItemsSource="{Binding source}">
<ListBox.ItemTemplate>
<DataTemplate>
<textbox x:Name="name"></ToggleButton> //or any tool
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I am new to MVVM, I have a checkedlistbox in a view with the list of titles(have bound the exposed property in ViewModel to this checkedlistbox control)...
Here is my XAML code that populates the ListCheckBox -
<ListBox x:Name="lstCode" ItemsSource="{Binding Code,Mode=TwoWay}" Grid.Row="1" Style="{StaticResource ListBoxStyle}">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox x:Name="chkBox" IsChecked="{Binding IsChecked,Mode=TwoWay}" Content="{Binding Code_Name}" Margin="0" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
This control shows the correct list of items with checkboxes for each item in the listbox...
What should be the code in viewmodel to make it work in two way - while getting the codes from database, it should automatically selected the code from the listcheckedbox and when the user selects one or more codes, the viewmodel should be able to know the items selected...
In general, for TwoWay binding, you will need to implement the INotifyPropertyChanged interface on the ViewModel you want to bind to.
In this case, your ViewModel will have to provide a property that returns a collection that your view can bind to, e.g. an ObservableCollection.
This ObservableCollection already allows you to add, update, and delete items in that list in a way that automatically communicates the changes between View and ViewModel.
For the rest I suggest to start digging into MVVM depths. To fully take advantage of WPF's capabilities, you will need to understand the basics for yourself. A great starting point is this SO thread: MVVM: Tutorial from start to finish?
I am somewhat new to WPF and Data Binding, it seems very powerful. I'm wondering if there's a way to have a set of labels, and have there Content property all binded to a different index in array of strings. So then as the array is updated, the labels automatically change too.
The xaml syntax is still a bit foreign to me and I haven't been able to get it to work.
If this is a dynamic set of labels, then you may be better off using an ItemsControl, and changing its ItemTemplate to display a label for each item in the collection that it is bound to (a collection of strings in your case).
Something like:
<ItemsControl ItemsSource="{Binding MyLabelStrings}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Label Content="{Binding}" ... />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
As Bojin mentions, if you wish your UI to update if strings are added/removed from the collection, then use an ObservableCollection for the MyLabelStrings property.
I have a ObservableCollection that's bound to a ListBox in WPF. I want the ListBox to be editable, and for the editing changes to be saved to the collection. Since WPF doesnt provide an editable listbox, I've tried creating my own by changing the ListBox.ItemTemplate.
<ListBox.ItemTemplate>
<DataTemplate>
<TextBox Name="EditableText" Text="{TemplateBinding Content}"/>
</DataTemplate>
</ListBox.ItemTemplate>
Changing the ItemTemplate gives me editable boxes, but any changes to the textboxes dont get saved to the ObservableCollection. Is there a way to have an editable ListBox with two way binding?
You cannot do it this way.
To achieve that kind of trick, you would need your items to be "holder classes" that expose a property you can bind your textbox to.
To understand it, imagine the following pseudo sequence of calls:
class ListBox
{
Bind(Items)
{
foreach(var item in Items)
{
DataTemplate Template = LoadTemplateForItem(item.GetType()); // this is where your template get loaded
Template.Bind(item); //this is where your template gets bound
}
}
}
Your template (the DataTemplate with the listbox) is loaded and the item (which I assume is a string in your case) gets passed in.
At this point, it only knows the string, and cannot influence anything upwards. A two-way binding cannot influence the collection because the template does not know in which context it is being used, so it cannot reach back to the original collection and modify its contents.
For that matter, this is the same thing for the TextBox. If it is not given a conainer and a property name, it has nowhere to "store back" the changes.
This basically the same as passing a string into a function call. The function cannot change which string was passed in (ignoring tricks such as by-reference argument passing).
To get back to your case, you need to build a collection of objects which expose a property containing the value that needs to be edited:
public class MyDataItem
{
string Data { get; set;}
}
Then you can bind your ListBox to a collection of those items and modifiy your datatemplate:
<ListBox.ItemTemplate>
<DataTemplate>
<TextBox Name="EditableText" Text="{Binding Data, Mode=TwoWay}"/>
</DataTemplate>
</ListBox.ItemTemplate>
Bind to a model property -- i.e. a property of the data object -- rather than to a view property such as Content. For example:
// model class
public class Widget : INotifyPropertyChanged
{
public string Description { ... }
}
<!-- view -->
<DataTemplate>
<TextBox Text="{Binding Description}" />
</DataTemplate>
Note this will not work if your ItemsSource is ObservableCollection (because there's no property to bind to).