I have a ListBox having ComboBoxes as ListItems. The ComboBox in each ListItem is created using ListBox's ItemTemplate.
Now, suppose I have 5 ListItems. i.e. 5 ComboBoxes.
For the 1st ListItem i.e. 1st ComboBox I would like to have all the Items from database as ItemsSource.
For the 2nd ListItem i.e. 1st ComboBox I would like to have all the Items from database as ItemsSource.
For the 3rd ListItem i.e. 1st ComboBox I would like to have only the selected Items from above Comboboxes as ItemsSource.
For the 4th ListItem i.e. 1st ComboBox I would like to have only the selected Items from above Comboboxes as ItemsSource.
For the 5th ListItem i.e. 1st ComboBox I would like to have only the selected Items from above Comboboxes as ItemsSource.
So, I think I have to use different DataSource for different ComboBoxes.
And for that to happen I have the following starting code:
<ComboBox....>
<ComboBox.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="ParentListBox.SelectedIndex" Value="0">
<Setter Property="DataSource" Value="{Binding Path=ListCorrespondingToValue1}"/>
</DataTrigger>
<DataTrigger Binding="ParentListBox.SelectedIndex" Value="Non-0">
<Setter Property="DataSource" Value="{Binding Path=ListCorrespondingToValue2}"/>
</DataTrigger>
</Style.Triggers>
</Style>
<ComboBox.Style>
</ComboBox>
Now, my question is what should I use insead of ParentListBox.SelectedIndex in the above code and what should I replace Non-0 with?
You don't use a DataTrigger for the non zero part... you just set it as a Setter in the Style, so that becomes the default value and then the DataTrigger changes the DataSource property only when the value is 0. Try this:
<ComboBox....>
<ComboBox.Style>
<Style>
<Setter Property="DataSource" Value="{Binding
Path=ListCorrespondingToValue2}"/>
<Style.Triggers>
<DataTrigger Binding="ParentListBox.SelectedIndex" Value="0">
<Setter Property="DataSource" Value="{Binding
Path=ListCorrespondingToValue1}"/>
</DataTrigger>
</Style.Triggers>
</Style>
<ComboBox.Style>
</ComboBox>
Related
I am using WPF to make a program with DataGrid. I have a Delete button and when I select one row in DataGrid, the button enables and I can use it. So if SelectedIndex is bigger than -1 the button enables. But I found out, the SelectedIndex is set to 0 by default, so it's like the first row is always selected.
Is there any other property of DataGrid I could use? Or is there some other way to make this work?
You can use DataTrigger on button to handle the disable/visible of buttons, something like :
<Button.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=nameOfDataGrid, Path=SelectedItem}" Value="{x:Null}">
<Setter Property="IsEnabled"Value="False"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
I have two list boxes which are bound to same observable collection. Basically one list box is a document tray where I drag & drop documents and other is a regular list box where I give the option to edit the file name. I want to highlight the items in both the listboxes. For example when the user selects a document in one listbox (tray) I want the list item with textbox in the other to be highlighted and likewise when I click on the text box in the other list box I want the item in the tray to be selected. I have my code as below.
In the Document Tray list box I have code as below.
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" />
</Style>
</ListBox.ItemContainerStyle>
Similarly in the other list box I have the style like this
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" />
<Style.Triggers>
<Trigger Property="IsKeyboardFocusWithin" Value="true">
<Setter Property="IsSelected" Value="True"></Setter>
</Trigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
When I select an item in the document tray the item is getting selected in the other list box. When I click on the text box or select an item in other list box the item is not getting selected in the tray list box. Also I noticed if I comment the focus trigger the items are getting selected appropriately. I want the selection to be propagated on focus also.
I am assuming you are binding your ListBox to data in code-behind (view model or otherwise) via a property, e.g. YourItems:
<ListBox ItemsSource="{Binding YourItems}">
<ListBox.ItemContainerStyle>
...
</ListBox.ItemContainerStyle>
</ListBox>
Create another property of the type that's within the collection in your code-behind, also (e.g. called YourSelectedItem. Then just add the following line inside BOTH of your Listbox definitions:
<ListBox ItemsSource="{Binding YourItems}"
SelectedItem="{Binding YourSelectedItem, Mode=TwoWay}">
As long as both are bound two-way, then they should stay in-sync with each other.
I would not use setters in the style to set IsSelected (discard the lines <Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" />). The ListBoxes themselves have properties to handle that if you can bind to a common item in code-behind as shown above. I'd need to try it, but then hopefully your trigger would work also since you won't have competing IsSelected triggers/styling.
I think the key thing here is that I've found that sometimes you cannot set something via trigger IF you've also set the same property via a style, so use SelectedItem on the ListBox parents, instead of an IsSelected style on each item.
I have a DataGrid with a combobox assigned of Customer IDs, Each Customer ID may have many Account IDs which are assigned in their own combo box. All I want to do is, when a user selects a Customer ID from the combobox, the Account IDs are then updated with the specific CustomerID that was chosen.
I think I am nearly there with the code.
Here I have the itemsource of the customerId applied inside the combobox elementstyle. As you can see I have a property of SelectedItem when an Item is selected from the customer box.
<DataGridComboBoxColumn.ElementStyle>
<Style TargetType="ComboBox">
<Setter Property="ItemsSource"
Value="{Binding DataContext.EntityCollection,
RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType=Window}}"/>
<Setter Property="DisplayMemberPath" Value="Name"/>
<Setter Property="SelectedItem" Value="{Binding SelectedItem}"></Setter>
<Setter Property="HorizontalAlignment" Value="Center"></Setter>
</Style>
</DataGridComboBoxColumn.ElementStyle>
So inside the Combobox of the Account Id, I am not sure where to put the SelectedItem.AID code...
I have put it inside the SelectedValueBinding property in the first line, but it doesnt work. do I need to put SelectedItem inside the Itemsource porperty inside the EditingElementStyle tag?
<DataGridComboBoxColumn SelectedValueBinding="{Binding SelectedItem.AID}" SelectedValuePath="SID" Header="SID" Width="70">
<DataGridComboBoxColumn.EditingElementStyle>
<Style TargetType="ComboBox">
<Setter Property="ItemsSource"
Value="{Binding DataContext.EntityCollection,
RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType=Window}}"/>
<Setter Property="DisplayMemberPath" Value="AID"/>
</Style>
</DataGridComboBoxColumn.EditingElementStyle>
<DataGridComboBoxColumn.ElementStyle>
<Style TargetType="ComboBox">
<Setter Property="ItemsSource"
Value="{Binding DataContext.EntityCollection,
RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType=Window}}"/>
<Setter Property="DisplayMemberPath" Value="AID"/>
<Setter Property="HorizontalAlignment" Value="Center"></Setter>
</Style>
</DataGridComboBoxColumn.ElementStyle>
However I could be way off, so any help I would be grateful.
Thanks
<Setter Property="ItemsSource" Value="{Binding DataContext.EntityCollection,
I'm not entirely sure if that is possible, though I would not recommend using that this way.
Bind your ViewModel in the code behind to the DataContext of your View. Now you can bind the ItemsSource to any ObservableCollection Property in your ViewModel. That'd probably be your EntityCollection
Well, when using a DataGridComboBoxColumn, all you need to do, is to tell this column where the data is located by binding the target property.
If you'd have a list of Customer applied to your DataGrid and your property is named ID, your markup might be as follows:
SelectedValueBinding="{Binding ID, Mode=TwoWay}"
Checking the Mode is highly required in order to transmit changes made to your property.
Now, to apply any changes to your other ComboBox, e.g. adding or creating items, you need to use another ObservableCollection and bind it to that second Combobox. If you done that, you can control the items of the second ComboBox when any changes are made to the first one.
Just a short sample how this might look:
private uint _ID;
public uint ID
{
get { return _ID; }
set
{
if (_ID == value) return;
_ID = value;
NotifyOfPropertyChange("ID");
// Do something with your second ComboBox.
// You could create another ObservableCollection and bind that to your second ComboBox and add some items representing the Account IDs
}
}
Don't forget to notify your View when making changes.
If that wasn't the answer you are looking for, please be more specific. Your actual question was very hard to read, I only understood the first paragraph and explained, how you can archive what you want to do.
I have a ComboBox, bound to a DataTable. The ComboBox displays a list of values, pulled from the "wellId" column of the DataTable. The ComboBox is also styled so that I can insert a custom item into the list simply by adding a dummy row to the DataTable with the wellId field set to "(settings)".
<ComboBox IsEditable="True" Name="comboWell" ItemsSource="{Binding}">
<ComboBox.ItemContainerStyle>
<Style TargetType="{x:Type ComboBoxItem}">
<Setter Property="Content" Value="{Binding wellId}" />
<Style.Triggers>
<DataTrigger Binding="{Binding wellId}" Value="(settings)">
<Setter Property="Content" Value="Customize..." />
</DataTrigger>
</Style.Triggers>
</Style>
</ComboBox.ItemContainerStyle>
</ComboBox>
For the most part, this works great. It shows the list, and all items (including the dummy items) are selectable in the drop-down list.
However, after selecting an item from the list, whether it is a real item or a dummy item, the ComboBox doesn't show the selected item properly. Rather than showing the same value displayed in the drop-down list (the "wellId" column from the DataTable), it instead just displays the string "System.Data.DataRowView". No matter what I select, it always displays the same thing.
If I specifically set the DisplayMemberPath on the ComboBox to "wellId", then it displays the selected item properly. However, this messes up all of the other styling I have applied, resulting in the drop-down list being filled with blank entries.
How do I get the ComboBox to display the selected item properly?
Change your ComboBox to set the ItemTemplate instead of the ItemContainerStyle, and remove IsEditable=True. If IsEditable=True then the SelectedItem will get displayed in a TextBox, and if a TextBox.Text is bound to an item, it will display the .ToString() of that item
<ComboBox Name="comboWell" ItemsSource="{Binding }">
<ComboBox.ItemTemplate>
<DataTemplate>
<ContentControl>
<ContentControl.Style>
<Style TargetType="{x:Type ContentControl}">
<Setter Property="Content" Value="{Binding wellId}" />
<Style.Triggers>
<DataTrigger Binding="{Binding wellId}" Value="(settings)">
<Setter Property="Content" Value="Customize..." />
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Is there a way to programmatically highlight a row and column in the WPF datagrid? I am using the scrollIntoView method to jump to that row and column. I'd like to highlight that row as well to highlight to the user that this is what's important. Thanks!
If you have a business object for whatever is represented in the datagrid, in the DataGrid.RowStyle I would use a DataTrigger bound to a boolean in the object representing the row. Then when you ScrollIntoView you could set this boolean and let XAML handle setting the row color for you. It might get weird because then you would have to reset any other ones set. But I think this could be an easy solution.
<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsSelected}" Value="True">
<Setter Property="Background" Value="Red" />
</DataTrigger >
</Style.Triggers>
</Style>
</DataGrid.RowStyle>