Binding Text Property of child element of ComboBoxItem - wpf

I have a WPF ComboBox with a static list of people with an image and first name. I am trying to bind the selected FirstName to a db table. The way I am doing it now (obviously wrong) I am only binding the object and hence writing:
System.Windows.Controls.ComboBoxItem
to my db table.
How can I bind the FirstName from the selected ComboBoxItem from the TextBlock.Text property? Is there a way to do this purely in WPF?
<ComboBox Text="{Binding Path=FirstName}">
<ComboBoxItem>
<StackPanel Orientation="Horizontal" >
<Image Source="/Images/Alice.png" />
<TextBlock Text="Alice" />
</StackPanel>
</ComboBoxItem>
<ComboBoxItem>
<StackPanel Orientation="Horizontal">
<Image Source="/Images/Bob.png" />
<TextBlock Text="Bob" />
</StackPanel>
</ComboBoxItem>
</ComboBox>
I am saving the changes to the db table on a button click event
private void SaveAndClose_Click(object sender, RoutedEventArgs e)
{
bindingView = (BindingListCollectionView)myCollection.View;
bindingView.CommitEdit();
db.SubmitChanges();
}

Instead of hard-coding the comboboxitems, you should use a datatemplate. Then, you should use the SelectedValuePath to select the value based on the FirstName property in your items. Then you can bind to the textbox.
If you want to bind to the textbox in xaml directly, you'll need to name the element (x:Name="myTextBox"). Then, bind your combobox's SelectedValue like so: SelectedValue="{Binding ElementName="myTextBox", Path="Text"}".
In general, I don't think binding a combobox to a textbox is a very good idea.

Related

Consuming Complex Comboboxes WPF

I want to have complex combobox with checkboxes, text, and may be a thumbnail. I have already looked at the following links which helped me alot while building complex comboboxes.
http://blogs.microsoft.co.il/blogs/justguy/archive/2009/01/19/wpf-combobox-with-checkboxes-as-items-it-will-even-update-on-the-fly.aspx
Looking for a WPF ComboBox with checkboxes
But, I can not find a way to consume these complex usercontol in my application. I am new to WPF, so any kind of demonstration support would be highly appreciated.
Dean, I was looking a solution of how to bind in code behind file with following example mentioned in an SO post earlier.
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding IsSelected}"
Width="20" />
<TextBlock Text="{Binding DayOfWeek}"
Width="100" />
</StackPanel>
</DataTemplate>
So the question is, Do I need DataTable or something else to bind my list of Checkboxes and Titles with this combobox template?
Thanks in Advance
A Combobox is an ItemsControl. All ItemsControls can be filled "hardcoded" with items or containers.
This adds a new entry in the combobox, and wrappes the string into an ItemsContainer, which is a ComboBoxItem.
<ComboBox>
<sys:string>Hello</string>
<ComboBox>
Here we create a combobox item directly, and add its content to a string with the value "Hello"
<ComboBox>
<ComboBoxItem Content="Hello"/>
<ComboBox>
Both look visually the same. Its important to understand that in the first case the ComboBox takes care of wrapping our, to the ComboBox unknown type string, into an ComboBoxItem, and uses a default DataTemplate to display it. The default DataTemplate will display a TextBlock and calls ToString() on the given data item.
Now to have dynamic data, we need a ObservableCollection with our data items.
class Employee
{
public BitmapSource Picture {get;set;}
public string Name{get;set}
}
ObservableCollection<Employee> employees;
myComboBox.ItemsSource = employees;
We have a DataClass called Employee, an observable Collection which holds many of our dataitem, and set this collection as the ItemsSource. From this point on, our Combobox listens to changes to this collection. Like adding and removing Employees and automatically takes care of wrapping the new Employee into a ComboBoxItem. Everything is done automatically. The only thing we need to do is to provide a proper DataTemplate. The combobox doesn't know how to "display" an employee and thats exactly what a DataTemplate is for.
<DataTemplate x:Key="employeeTemplate">
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Picture}"/>
<TextBlock Text="{Binding Name}"/>
</StackPanel>
</DataTemplate>
We know an employee is wrapped in a ComboBoxItem, and the ComboBoxItem uses a provided Datatemplate to display its data, which means that inside the DataTemplate we can use Binding to access all properties on the data item.
Hope that helps you.
to just answer your question. all you need is a collection of an object with at least 2 public properties (IsSelected as bool and DayOfWeek as string) and just set these collection as the itemssource.
so all you need is a collection of such an object. just comment if you need an example.
ps: pls read through the www for wpf and binding to get the basics.
you could simple add the items directly
<ComboBox>
<ComboBox.Items>
<ComboBoxItem>
<TextBlock Text="test text" />
</ComboBoxItem>
<ComboBoxItem>
<CheckBox Content="test checkbox" />
</ComboBoxItem>
<ComboBoxItem>
<Button Content="test button" />
</ComboBoxItem>
</ComboBox.Items>
</ComboBox>
or if you want to use ItemsSource, the a DataTemplateSelector would be required
<ComboBox>
<ComboBox.ItemTemplateSelector>
<local:MyCustomTemplateSelector />
</ComboBox.ItemTemplateSelector>
</ComboBox>
here is a link that explains DataTemplateSelectors
http://msdn.microsoft.com/en-us/library/system.windows.controls.itemscontrol.itemtemplateselector.aspx

wpf access lisbox selected item if it isn't string

I have a listbox which displays Name property from an array of Movie objects
<ListBox Name="listBox1" SelectionChanged="listBox1_SelectionChanged">
<ItemsControl ItemsSource="{Binding}" >
<ItemsControl.ItemTemplate >
<DataTemplate >
<TextBlock Name="textBlock1" Text="{Binding Name}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ListBox>
How can I access the text of the textBlock that's inside the ListBox in Code?
I must use the value of the Name property in my code
The selected item reported by the listbox exposes you the object that owns the Name property bound in the TextBlock. At this point the game is over.
When you do the above every textblock inside the itemscontrol has a name textblock1 that too with a scope limited to each item container.
If you want each of those textblocks individually, I usually do something like:
<TextBlock Text="{Binding Name}" Loaded="TextBlock_Loaded"/>
And in the code register those textboxes in whatever way you wish. A list probably,
List<TextBlock> TextBlockList = new List<TextBlock>();
private void TextBlock_Loaded(object sender, RoutedEventArgs e)
{
TextBlockList.Add((TextBlock)sender);
}
And for example, access the stuff as:
String FirstItem = TextBlockList.ElementAt(0).Text;

How can I set the XAML for the first WPF RadioButton in a ListView control to be checked by default?

I have a WPF ListView control containing a number of RadioButton controls using data binding. I'd like the first RadioButton in the group to be checked by default, preferably set in the XAML rather than programmatically, but haven't managed to achieve this.
My XAML for the control is:
<ListView ItemsSource="{Binding OptionsSortedByKey}" >
<ListView.ItemTemplate>
<DataTemplate DataType="{x:Type Logging:FilterOptionsRadioListViewModel}">
<RadioButton Content="{Binding Value}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
The OptionsSortedByKey property is a SortedList.
I have done this clumsily by setting the IsChecked property of the RadioButton control in the Loaded event:
var button = sender as RadioButton;
if (button != null)
{
if (button.Content.ToString().ToUpperInvariant() == "ALL")
{
button.IsChecked = true;
}
}
I'd far prefer to do it via data binding in the XAML. Is there a simple way?
You could:
<RadioButton IsChecked="{Binding RelativeSource={PreviousData}, Converter={StaticResource NullAsTrueConverter}}"/>
Where the converter returns true if the value is null.
That said, an MVVM-based approach would make this a snap. You'd just:
<RadioButton IsChecked="{Binding IsChecked}"/>
And then your primary view model would set IsChecked to true for the first child view model in the collection.

Getting the SelectedItem from a combobox in a DataTemplate

Lets say I've got a DataTemplate like so
<DataTemplate x:Key="Body">
<StackPanel Orientation="Horizontal">
<ComboBox ItemsSource="{Binding Path=Person.Children}"></ComboBox>
<Button Click="Button_Click">Hello</Button>
</StackPanel>
</DataTemplate>
Which shows a list of ComboBoxes followed by a button.
Now, on clicking the button I need to discover the value in the combo next to the button pressed. I can get the data context as below but can't work out how to get the combos SelectedItem
private void Button_Click(object sender, RoutedEventArgs e)
{
// Can get the data context
var p = ((Button)sender).DataContext as Person;
// How to get the value in the combo ...?
}
you can also reference the combobox in your codebehind if you give it a name. However its cleaner to use a separate class to do your logic than the code behind. Such as a viewmodel.
then you could also do something like this...
<DataTemplate x:Key="Body">
<StackPanel Orientation="Horizontal">
<ComboBox ItemsSource="{Binding Path=Person.Children}"
SelectedItem="{Binding Path=SelectedChild}"
IsSynchronizedWithCurrentItem="True"/>
<Button Command="{Binding Path=ButtonCommand}">Hello</Button>
</StackPanel>
</DataTemplate>
Instead of using the Click event handler, use a Command and bind the CommandParameter property to the ComboBox.SelectedItem. Then in your command's executed logic, you can use the parameter.

Silverlight: How to dynamically bind a ComboBox in a ListBox ItemTemplate?

I have a list box that requires at least one ComboBox. I couldn't find a way to place the ComboBox in the ItemTemplate I use.
...
<DataTemplate x:Key="parts_template">
<StackPanel Orientation="Horizontal">
<TextBlock .../>
<ComboBox .../>
</StackPanel>
</DataTemplate>
...
<ListBox x:Name="lb_parts" ItemTemplate="{StaticResource parts_template}" .../>
...
How do bind that ComoBox in the DataTemplate to an ObservableCollection in the code behind?
Another thing you could try is subscribe the Loaded event on the ComboBox.
Then you can set the ComboBox.ItemsSource in the EventHandler to MyObservableCollection.
Have a look
XAML:
<DataTemplate x:Key="parts_template">
<StackPanel Orientation="Horizontal">
<TextBlock .../>
<ComboBox Loaded="ComboBox_OnLoaded">
<!-- ComboBox ItemTemplate -->
</ComboBox>
</StackPanel>
</DataTemplate>
C# Code Behind:
private void ComboBox_OnLoaded(object sender, EventArgs e)
{
((ComboBox)sender).ItemsSource = MyObservableCollection;
}
Okay, here is how you can add a ComboBox to the ListBox in the code behind.
Create a ComboBox
ComboBox x = new ComboBox();
If you have a data source that populates the ComboBox then you can just bind that
x.ItemsSource = e.Result;
If you do not and want to manually add items to the ComboBox:
ComboBoxItem y = new ComboBoxItem();
Set the Content of the Item to what you want displayed in the ComboBox
y.Content = "Hello";
Now all that is left, is to add the ComboBoxItem to the ComboBox (only if you are creating the Items manually), and then the ComboBox to the ListBox
x.Items.Add(y);
//testing is my ListBox
testing.Items.Add(x);
You should be able to set the data context to the List itself
lb_Parts.DataContext=myCollection;
Then you should be able to bind to it in the template
<DataTemplate x:Key="parts_template">
<StackPanel Orientation="Horizontal">
<TextBlock .../>
<ComboBox ItemSource={Binding}/>
</StackPanel>
</DataTemplate>

Resources