How to set focus to a control in a TreeViewItem when selected - wpf

I have a TreeView in which the items are defined by HierarchicalDataTemplates. Each TreeViewItem that is created has some TextBoxes in it. When a TreeViewItem is selected I want to set the Keyboard Focus to a TextBox of the TreeViewItem (the TextBoxhas the name TextBox1). How can I do this?

There are many ways you can do this. Here is just one of them. Use mine FocusExtension. IsFocused attached property. Bind it to TreeViewItem.IsSelectedProperty if you don't have a ViewModel underneath. Something like
<TextBox local:FocusExtension.IsFocused="{Binding IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TreeViewItem}}}" />
should work. I typed that from head and didn't check the syntax. Be careful while copy-pasting :).

Related

listview checkbox binding wpf MVVM

I am trying to get the bool value of the checkbox present in the Listview. I am binding to a bool public property "Assignm" in the view model. I tried the below binding pattern but the problem is if i select one checkbox it selects all checkboxes and vice versa. I think this is because relativesource is listview and it works on complete listview. I also tried changing the relative source to ListviewItem but that didn't trigger anything. Can someone help me please. Do i need to change something here ?
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox Tag="{Binding MU_Identifier}" IsChecked="{Binding DataContext.Assignm, RelativeSource={RelativeSource FindAncestor, AncestorType=ListView}}">
</CheckBox>
</DataTemplate>
</GridViewColumn.CellTemplate>
Because your binding for IsChecked property is Assignm property which seems to be one property of your view model.
If there is a boolean property named Assignm for the data model of the DataSource of ListView, then just change the binding like this: {Binding Assignm}, as Tag property does.
All your items are bounded to a single property, so when one item changes a property in your context it changes on other items.
To provide correct work all your items from ItemsSource should have property IsChecked.
Check this Example

WPF MVVM: How to enable/disable buttons in ListBox if I'm using a DataTemplate

I have a WPF/MVVM app with a ListBox which displays data through a DataTemplate. I managed to change the selected item in the ListBox when pressing a button so the CommandParameter is linked to the ListBox's SelectedItem, but I cannot get the buttons to be enabled/disabled correctly in the same way. For example, if I have 2 items and the button should be enabled in one and disabled in the other, when I select an element BOTH buttons have the same state, and they BOTH change state when I select another item.
I am using a RelayCommand as used in many MVVM Frameworks.
Here is my XAML (removed "not interesting" parts):
<UserControl.Resources>
<DataTemplate x:Key="ItemTemplate">
<Grid>
<Button Content="Something" Name="EnabledDisabledButton" Click="Button_Click"
Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Path=DataContext.SomeCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource AncestorType={x:Type ListBox}}, Path=SelectedItem}"/>
</Grid>
</DataTemplate>
<Style TargetType="{x:Type ListBoxItem}" x:Key="ContainerStyle">
<Setter Property="ContentTemplate" Value="{StaticResource ItemTemplate}" />
</Style>
</UserControl.Resources>
<ListBox x:Name="myListBox" ItemsSource="{Binding ElementList}"
IsSynchronizedWithCurrentItem="True" ItemContainerStyle="{StaticResource ContainerStyle}"/>
I tried to pass the SelectedItem as a parameter to the RelayCommand's CanExecute method, but the result was the same as before.
Is there a way to pass the actual ListBoxItem in which the button "lives in" as a parameter to the command, so each one will be processed separately by the CanExecute method? Would it work if I got this? (right now I am handling the Click event to select the correct item in the list before executing the command).
In my CanExecute method I am evaluating some property of the SelectedItem in order to enable/disable the corresponding button. An alternative would be to evaluate this property for all elements, but I cannot think of a way to do it inside the ViewModel, and then communicate to the view the result (if it is even possible while using a DataTemplate for the items).
Thanks for your input, regards!
Converting My comment into an answer:
Why not just CommandParameter="{Binding}"?
You mention "MVVM" in the question, but it seems you use the MVVM way to your full advantage.
I would not have a Button_Click event in the style at all. That is because it is in fact a style, which per definition could be changed to another style which does not have the same event, which again will make the application stop working as wanted if you choose to have a style-based app in the future.
A rule I use is that a style is a style. A style has to do with the UI and "looks" of the app.
Functionality should be separate from the UI. The programmer can define the Command, and the designer can decide how the user will use that in the best way.
That's exactly where the code separation from the MVVM pattern cames into grip.
To separate the "looks" and user behavior and the app's logic.
Like...it should not matter to the model if a command fires from a button, a menu, a datacontext or a key stroke.
If this particular problem was handled to ME, I would solve it by having a HOLDER-class.
This is a class (DependencyObject which implements INotifyPropertyChanged) that holds a ICommand property as well as the "row" that will be displayed in the various rows in the ListBox.
The ICommand property will be bound to the Button, having the row (class) itself as CommandParameter to the call.
Then the actual row would be used in the ItemTemplate on the ListBox, with Bindings to different elements (proprty with or withouy Converters) to make whatever desired display available.
I hope I explained good enough...
Feel free to ask more if you want more details to my solution alternative.

What's a better way to bind header checkbox to user control's datacontext?

I have a workable solution but I'm pretty convinced there's a better way of writing this.
I have a User Control with a Data Grid inside. The Data Grid's ItemsSource is set to {Binding Path=MyView} where MyView is an ICollectionView property of the View Model. The User Control's data context is set to the View Model.
In the data grid, I have a check box header. I want to bind the IsChecked state of the checkbox to a property in the View Model.
This is what I have so far and it seems to work, but I'm concerned this binding is unnecessarily complex. The UI is pretty basic so I would expect the binding to be more straightforward to write than it was.
Is there a better way to express such a binding?
<DataGridTemplateColumn.HeaderTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Views:MyUserControlClass}}, Path=DataContext.AllRowsSelected}" />
</DataTemplate>
</DataGridTemplateColumn.HeaderTemplate>
In such situations I use
ElementName=userControl
instead of
RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Views:MyUserControlClass}}
Also you can use
{Binding Parent.DataContext.AllRowsSelected, ElementName=LayoutRoot}
In this case I assume that LayoutRoot is the name of the element who's parent is the user control. Parent is its property. So binding is set to parent's DataContext property.
I prefer the last variant, because providing name for user control limits its usage.
EDIT
About LayoutRoot. This name is often provided for the top element in a Window or a UserControl, or just some layout:
<Window ...>
<Grid Name="LayoutRoot">
...
</Grid>
</Window>
There's nothing special about this name. Just often used. Same situation as with namespace aliases in xaml: sys (points to mscorlib), local (points to your application namespace), etc.

Setting RelativeSource correctly

I have a combo box on a xaml form (MainWindow).
I set the Items source to an ObservableCollection in the code behind. To populate the Combo box I used Relative Source (it sits inside an ItemsControl), which worked great (without it, if did not populate):
ItemsSource="{Binding SelectableItems, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
I have now factored out the ObservableCollection into a seperate View Model Class, named 'MainWindowViewModel', the combo box does not populate.
I have set the DataContext of the MainWindow to my ViewModel and have checked that it populates other controls as expected, which it does.
How should I construct the RelativeSource so the combo box populates?
Thanks
Joe
I needed to add the Path at the end, thus:
ItemsSource="{Binding SelectableItems, RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=DataContext.SelectableItems}"
You do not want to use a RelativeSource any longer. If you don't specify a RelativeSource (or Source, or ElementName), then the binding will resolve against the current DataContext. Since the DataContext is inherited, your ItemsControl obtains its DataContext from the parent Window. Thus, this binding will resolve against your view model.
ItemsSource="{Binding SelectableItems}"

WPF - prevent ListBox item selection

I would like to prevent selection of ListBoxItems in my ListBox. My DataTemplate has a checkbox and this should be the only thing the user can click or select.
How can I do that?
Thanks!
This is almost a duplicate question. In fact, you're asking two questions here:
Either style your ListBoxItem so that it doesn't show selection (look elsewhere on SO for that answer), or replace ListBox with ItemsControl if you don't need the other features that ListBox provides.
Bind your checkbox's IsChecked property to the parent ListBoxItem.IsSelected property:
<CheckBox
IsChecked="{Binding
RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType=ListBoxItem},
Path=IsSelected}"
/>
When your user will try to (un)check your checkboxes then item become 'active' in some way. And focused style will be applied. As far as i know there is no way to disable selection(because if you did your checkboxes will not work) but you can override focused(or selected) style of your listbox items

Resources