I have a custom WPF control - essentially a combo-box with check-boxes. The combo-boxes are successfully bound to a list of available items.
This control is to represent a field on a form. It is possible for the form to be completed already, in which case, the control must be rendered with the selected items - i.e. any items previously selected must be rendered as a checked CheckBox; it is here I'm running into trouble.
My first thought was to simply bind the IsChecked property - I don't think this can be done as the list of currently-selected-items is different from the list of available items which the ComboBox is bound to.
Basically, how do I gain access to the CheckBox object to set the Checked property to true? I've looked into this extensively and I can't fathom this out.
I'm using the ItemContainerGenerator approach - so when the user clicks on the drop-down, it is intended that a handler will iterate through the CheckBoxes and set the relevant boxes to checked.
Here's the XAML:
<ComboBox x:Name="FieldOptions"
ItemsSource="{Binding}"
HorizontalAlignment="Stretch"
Height="30"
KeyDown="FieldOptions_OnKeyDown">
<ComboBox.ItemTemplate>
<DataTemplate>
<CheckBox Name="checkbox"
Content="{Binding Path=Text}"
Uid="{Binding Path=ID}"
FontStyle="Normal"
Foreground="Black"
Checked="CheckBox_OnChecked" />
</DataTemplate>
</ComboBox.ItemTemplate>
Any thoughts would be much appreciated.
Related
The combobox is editable so user can also write. I have two usecases:
Get the text from combobox in a Lostfocus way, when user writes
something in the box and when he presses "Tab" then I want the text
from the combobox and I add the value in the itemsSource list.
When the users makes the selection from the combobox dropdown, I want that
selected item as soon he selects it and this time I dont
want to have it in Lostfocus manner but somewhat like
PropertyChanged way.
I tried the code which is given below:
<ComboBox Margin="3" x:Name="Combobox" SelectedItem="{Binding SelectedPath, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Text="{Binding PathLocation, UpdateSourceTrigger=LostFocus, ValidatesOnNotifyDataErrors=True}" IsTextSearchEnabled="True" VerticalContentAlignment="Center" ItemsSource="{Binding SelectedPaths}" IsEditable="True" Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="2" HorizontalAlignment="Stretch"/>
Things worked fine for the first time when the application starts but after some interactions the problem arises. When the user starts typing in the combobox the SelectedItem property of combobox triggers which is contrary to what I want in the first use case.
In short: when the user writes something in the combobox I want to have it in a Lostfocus manner and when he makes the selection from the dropdown of combobox I want to have it in a PropertyChanged manner.
Let me know if more details are required.
I removed the "IsTextSearchEnabled" property but it also didnt work then I came to know that "IsTextSearchEnabled" property of Comobobox is by default true, which is causing some values suggested by the combobox are setting in my properties. As soon as I made the "IsTextSearchEnabled" to false, it is working fine.
I have created search option using combobox, for example
In combobox1 items are m1,m2,m3,m4,m5 based on that, if m1 item selected then
another combobox2 displays with items a,b,c,d and if a item is selected another
combobox3 dispalys, based on last combobox it searches on the datagrid.
I think it is long process, use of many combobox makes it lenghty. Is any
other way is their to implement this. plz help
<ComboBox Grid.Column="1"
Grid.Row="1"
x:Name="cmbType"
VerticalAlignment="Top"
IsEnabled="{Binding IsOther}"
ItemsSource="{Binding Source={StaticResource enumTypeOfType}}"
SelectedItem="{Binding SearchType,Mode=TwoWay}"
SelectedIndex="{Binding CmdResIndex,Mode=TwoWay}"
IsSynchronizedWithCurrentItem="True"
SelectionChanged="DataSource1"
Margin="0,0,1,0">
</ComboBox>
So if i get this right, you have a collection a, which goes to collection b,etc, and the second collection will change based on the selected item of the first? You have to remember, that since the data will change for each selection, hard coding the value is out of the question.
Knowing this, WPF provides you with a great mechanism for this. Using a stackpanel, with a list view will actually work.
<ItemsControl ItemsSource="{binding collections}" ItemTemplate="{binding TemplateForListViewItems}" ItemPanelTemplate="{binding itemPanelTemplate}"></ItemsControl>
Now, with the items control, one can simply set an ItemTemplate/DataTemplate, to set the styling of each control. Linking to the onclick event, or using interactions, you can simply do collections.Add to add your new list view with generated data for the selection, and done.
<StackPanel DataContext="{StaticResource Employees1}">
<ListBox ItemsSource="{Binding}" DisplayMemberPath="Name"
IsSynchronizedWithCurrentItem="True"/>
<Label Content="{Binding Path=Count}"/>
<Label Content="{Binding Path=Name}"/>
</StackPanel>
How does the binding for the labels get resolved? How is it decided that the content of the second label is bound to Employees1.Count (and not to Employee.Count), while the first label is bound to
Employee.Name and synchonized with the listbox selection? Also, what if I would like to bind the first label to Employee.Count instead?
(Employee has properties Name (and possibly Count), Employees1 is an ObservableCollection of type Employee).
EDIT: So, the question here is WHY the first label displays the number of employees in the ObservableCollection, while the second label displays the name of a specific employee in the collection, the one that is currently selected in the ListBox. Apparently, the first label binds to the entire collection, and the second label to a specific employee in the collection. But why, and how to control this behavior.
From MSDN Data Binding Overview, Binding To Collections, section "Current Item Pointer":
Because WPF binds to a collection only by using a view (either a view
you specify, or the collection's default view), all bindings to
collections have a current item pointer.
and section "Master-Detail Binding Scenario":
This works because when a singleton object (the ContentControl in this
case) is bound to a collection view, it automatically binds to the
CurrentItem of the view.
In your example, the second Label automatically binds to the current item of the default view of the Employees1 collection. The first Label would also bind like this, but since the item object does not have a Count property it apparently falls back to a binding to the Count property of the collection itself. However i don't know if the latter behaviour is documented somewhere.
As Blam says - the labels have no relationship to the listbox - I think what you're trying to do here is bind an observableCollection of Employees with properties Count and Name to the listbox..
To do this you'll need an ItemsTemplate in the listbox
<ListBox ItemSource={Binding Employees1}>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Label Content="{Binding Count}" />
<Label Content="{Binding Name}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Let me try and answer the questions.
An ObservableCollection has a property Count.
As for getting a single property on the second label it is making some assumptions.
You might not get the same behavior in other version of .NET.
Should not bind a control that displays a single value to a collection.
If you want the selected item from the ListBox see this link
enter link description here
I have a ListBox ItemTemplate where I have a CheckBox that is Binded to a List<> that I am maintaining in my application.
My XAML:
<ListBox x:Name ="lstTasks">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="30,12,0,0">
<CheckBox IsChecked="{Binding use}" Unchecked="CheckBox_Unchecked" Tag="{Binding key}" Checked="CheckBox_Checked" />
<TextBlock Width="160" Text="{Binding key}" Margin="20,18,0,0" />
<TextBlock Text="{Binding value}" Margin="0,18,0,0"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
And :
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
lstTasks.ItemsSource = null;
lstTasks.ItemsSource = a.Words; //a.Words is the List<DataClass>
}
I have observed that the Checked and Unchecked events get fired on its own when I scroll in the list of these Items. I have logic attached to these Events and they mess the whole thing up by checking and unchecking random entries. This starts after I uncheck one of the items. (By default all the items are checked)
I am new to WPF and Windows Phone, what am I doing wrong.?
Firstly, Windows Phone does not use WPF. You are using Silverlight which is based on a sub-set of WPF. They are different technologies with different capabilities. Much of what you can do on one you can't do on the other.
It would help to see more of your code, particularly the viewmodel to get a complete picture of what's going on.
I suspect one of two things though:
1 - there is some logic somewhere based on the setting of the use property and as this is changed in the vm, the fact it is reflected in the UI and that triggers the events.
2 - You have a virtualized list inside your ListBox and as items are loaded it's triggering the UI updates (due to the binding) and that in turn is triggering the events.
Without being able to see more code it's hard to be more specific.
As an alternative to this approach you could use a 2-way binding of the use property and move the logic from your event handlers (for checked and unchecked) and into the property setter.
I have a ComboBox that uses an ItemTemplate as shown below. Somehow the Text property of the text box defined in the item template gets disconnected from the binding and stops being updated when the selected item changes.
The ComboBox.ItemsSource is bound to a DependencyProperty that is list of CatheterDefinition objects. The ComboBox.SelectedItem is bound to a DependencyProperty that is a single CatheterDefinition object.
<ComboBox
AutomationProperties.AutomationId="CatheterInfoModelFieldID"
VerticalAlignment="Center" HorizontalAlignment="Stretch"
ItemsSource="{x:Static PumpAndCatheter:CatheterInfoViewModel.CatheterModelDefinitions}"
SelectedItem="{Binding ElementName=UserControl, Path=ViewModel.SelectedCatheterModel, Mode=TwoWay, NotifyOnSourceUpdated=True}"
SourceUpdated="HandleModelSourceUpdated">
<ComboBox.ItemContainerStyle>
<!-- A style used to set the AutomationID based on the item goes here -->
</ComboBox.ItemContainerStyle>
<ComboBox.ItemTemplate>
<DataTemplate>
<!-- This line below is the location of the problem -->
<TextBlock Text="{Binding Converter={StaticResource CatheterModelDefinitionToStringConverter}}">
<!-- A style used to set the AutomationID based on the item goes here -->
</TextBlock>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
I have an automated test that produces a very strange behavior (I saw the same behavior a few time during the initial development of the code, but was unable to reproduce it manually) - The test that reproduces this selects an item form the ComboBox, then goes to another part of the application and takes some actions that end up saving this change in a data model. When the test returns to the screen with this ComboBox, it tries to select another item from the ComboBox. The SelectedItem changes, and the values that it is bound to change, BUT the text in the ComboBox does not change - somehow the binding to the Text property of the text box gets broken (or something)... The binding still executes (the converter still runs when the selection changes and it converts to the correct value), but the text property is never updated.
Thoughts? (I can't provide an example of this because it is a huge application and it is only reproducible under one test that I know of)
Broken bindings are most of the time caused by not calling (or not correctly calling) the OnPropertyChanged("PropName") method.
Without seeing your underlying implementation, I would say that this is most likely the source of the problem.