I have a treeview that need to refresh due to data changes. Is it
possible to refresh and select the last node that they were viewing when the tree view was been populated once again?
Thanks for any help.
For auto refresh you can create some ViewModel for treeView. Something like in my answer Binding a WPF TreeView to multiple Lists . To update selected item and expand it you should define in ViewModel IsSelected and IsExpanded properties (like Name property, but bool). And you should define ItemContainerStyle in your TreeView like this.
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/>
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
</Style>
</TreeView.ItemContainerStyle>
Related
I've a combobox like this:
<ComboBox x:Name="CountryMenuComboBox"
ItemsSource="{Binding Countries}">
<ComboBox.ItemContainerStyle>
<Style>
<Setter Property="IsEnabled" Value="{Binding IsRemoving}" />
</Style>
</ComboBox.ItemContainerStyle>
what I need to do is enable or disable the items inside the combobox using the property IsRemoving, but this property isn't located inside the itemsource Countries, so I need to access outside the itemsource. How can I do this for a style?
Is IsRemoving a property of the parent viewmodel that owns the Countries property? If so, try <Setter Property=“IsEnabled” Value=“{Binding DataContext.IsRemoving, RelativeSource={RelativeSource AncestorType=ComboBox}}” />
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 am currently using the code from this blogpost in order to have my TreeView highlight those items, which are currently hovered by the mouse. This is working as intended, however now I want the TreeViewItems to notify their attached ViewModels when they are hovered / not hovered.
However I'm at a loss on how I can achieve this. The corresponding XAML code looks like the following:
<Style TargetType="{x:Type TreeViewItem}">
<Style.Triggers>
<Trigger Property="Controls:TreeViewHelper.IsMouseDirectlyOverItem" Value="True">
<Setter Property="Background" Value="Green" />
</Trigger>
</Stile.Triggers>
</Style>
How can I bind the property from my ViewModel, named TreeNodeModel.IsHovered to the TreeViewItem (or probably the attached dependency property IsMouseDirectlyOverItem) so that I can react on those changes from within my code?
All the examples I found via google only explained how the set the background color. Thanks in advance for your time on the probably trivial answer.
In your Style, try adding a Setter which binds IsMouseDirectlyOverItem to IsHovered, and use the OneWayToSource binding mode to push the value the right way:
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="Controls:TreeViewHelper.IsMouseDirectlyOverItem"
Value="{Binding Path=IsHovered, Mode=OneWayToSource}" />
<Style.Triggers>
...
</Style>
EDIT: As IsMouseDirectlyOver is read-only, and read-only DPs can't be the target of any bindings, Fredrik Hedblad's PushBinding may be a possible workaround: OneWayToSource Binding for ReadOnly Dependency Property
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="pb:PushBindingManager.StylePushBindings">
<Setter.Value>
<pb:PushBindingCollection>
<pb:PushBinding TargetDependencyProperty="Controls:TreeViewHelper.IsMouseDirectlyOverItem"
Path="IsHovered" />
</pb:PushBindingCollection>
</Setter.Value>
</Setter>
<Style.Triggers>
...
</Style>
Unless I add DisplayMemberPath on the combobox it does not work. I think it should take it from Style?
I have the comboBox initially disabled. I see it can work when I open another tab with same DataTemplate. Once it works on one instance, it imdly starts working on all. Is is anything to do with tabs?
<Style x:Key="CollectionList" TargetType="ComboBox">
<Setter Property="IsReadOnly" Value="True"/>
<Setter Property="IsEditable" Value="True"/>
<Setter Property="IsSynchronizedWithCurrentItem" Value="False"/>
<Setter Property="DisplayMemberPath" Value="Name"/>
</Style>
<ComboBox ItemsSource="{Binding Items}"
Style="{StaticResource CollectionList}"
SelectedItem="{Binding Model.SelectedItem}" />
Change your Style="{StaticResource CollectionList}" to a DynamicResource
I am guessing it has something to do with the StaticResource getting loaded once, and the TabControl items getting loaded as needed