I have a ListBoxItem template with a TextBox element within. When the user clicks the TextBox, I should make the ListBoxItem as the SelectedItem of the ListBox.
<ListBox.ItemTemplate>
<DataTemplate>
<DockPanel Margin="4,0,4,0">
<TextBlock Text="{Binding Path=Value1, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
ToolTip="{Binding Path=Hint, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
VerticalAlignment="Center" />
<TextBox x:Name="TextField"
Margin="2,0,0,0"
Width="{Binding Path=ActWidth, Mode=OneWay}"
Visibility="{Binding Path=VisibleAct, Mode=OneWay}"
/>
</DockPanel>
</DataTemplate>
</ListBox.ItemTemplate>
I have the following Trigger to make the selection:
<ListBox.Resources>
<Style TargetType="ListBoxItem">
<Style.Triggers>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="IsSelected" Value="True" />
</Trigger>
</Style.Triggers>
</Style>
</ListBox.Resources>
Unfortunately, it works only for
an instant, when I change the focus, the selection disappears.
If I remove the trigger, it works normally but selecting the TextBox does not trigger the selection.
What should I do to make the selection permanent?
Your sample doesn't work because, if the trigger is false, your ListBoxItem is getting the value as it had before triggering. Your ListBoxItem is like 'ehmm, what I was..'.
So you have to set its SelectedValue by adding a default setter that binds its IsSelected state:
<Style TargetType="ListBoxItem">
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode="OneWay", RelativeSource={RelativeSource Self}}" />
<Style.Triggers>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="IsSelected" Value="True" />
</Trigger>
</Style.Triggers>
</Style>
Setting default setter for IsSelected as OneWay binding to itself will do the job. It will set IsSelected as it was, when the trigger is false.
You could write some code to set the SelectedItem property of the ListBox. You could handle the GotKeyboardFocus event for the TextBox:
<ListBox x:Name="lb2">
<ListBox.ItemTemplate>
<DataTemplate>
<DockPanel Margin="4,0,4,0">
<TextBlock Text="{Binding Path=Value1, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
ToolTip="{Binding Path=Hint, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
VerticalAlignment="Center" />
<TextBox x:Name="TextField"
Margin="2,0,0,0"
Width="{Binding Path=ActWidth, Mode=OneWay}"
Visibility="{Binding Path=VisibleAct, Mode=OneWay}"
GotKeyboardFocus="TextField_GotKeyboardFocus"
/>
</DockPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
private void TextField_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
TextBox textBox = sender as TextBox;
lb2.SelectedItem = textBox.DataContext;
}
Related
I've got a list box with SelectionMode set to Single and item template looking like this:
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical" Width="100" Margin="10" Cursor="Hand" >
<Image Source="/Assets/Images/folder_80closed.png" HorizontalAlignment="Center" />
<TextBox Text="{Binding Name}" BorderThickness="0" TextAlignment="Center" HorizontalAlignment="Center"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
Is there any way to change the value of image Source property in XAML based on if the item is selected or not? Something like pic bellow, where item4 is selected.
You may use an Image Style with a DataTrigger on the IsSelected property of the current ListBoxItem:
<Image HorizontalAlignment="Center">
<Image.Style>
<Style TargetType="Image">
<Setter Property="Source"
Value="/Assets/Images/folder_80closed.png"/>
<Style.Triggers>
<DataTrigger
Binding="{Binding IsSelected,
RelativeSource={RelativeSource AncestorType=ListBoxItem}}"
Value="True">
<Setter Property="Source"
Value="/Assets/Images/some_other_image.png"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
So I have a Listbox whose items contain an Expander. What I am trying to do is bind the IsExpanded property to the IsSelected property of the parent ListBoxItem. The whole purpose is that if they selected a different listbox item it'll collapse the current selected item and expand the new slected item.
UPDATE (CODE):
<ListBox SelectionMode="Single">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="Padding" Value="0" />
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<Boreder BorderThickness="0,0,0,1"
BorderBrush="Black">
<Expander IsExpanded={Binding RelativeSource={RelativeSource AncestorType=ListBoxItem},
Path=IsSelected} />
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
The property/binding I was looking for was IsExpanded="{Binding Mode=TwoWay, Path=IsSelected, RelativeSource={RelativeSource AncestorType=ListBoxItem, Mode=FindAncestor}}"
I've to change the Text property of a combo box when IsEnabled sets to false and it can manually selects field from the items source when IsEnabled is true from the same control, is this possible?
XAML:
<ComboBox Name="cmbIntervals"
Grid.Row="5"
Grid.Column="1"
Width="150"
HorizontalAlignment="Left"
VerticalAlignment="Top"
IsEnabled="{Binding ElementName=chkBox,
Path=IsChecked}"
ItemsSource="{Binding Source={x:Static res:Parameters.Instance},
Path=Intervals}"
Text="{Binding [Intervals], Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}" >
<ComboBox.Style>
<Style TargetType="{x:Type ComboBox}">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Text" Value="1"/>
</Trigger>
</Style.Triggers>
</Style>
</ComboBox.Style>
</ComboBox>
Just check in ViewModel
if(!IsChecked)
{
TextProperty="1"; //Propery to bind to ComboBox Text
}
I have an textblock, expander and a textbox...
these are inside the header of a listview column.
TextBlock is for listview column name, on click of expander...textbox will be displayed...and user can seartch the listview based on that column. The textbox is collapsed by default.
My requirement is, when user click on the expander, textbox should be displayed to the user...and focus should be on the textbox.
With the below XAML, I am able to display the textbox on click of expander and set the focus(cursor) on my textbox. But that cursor is no blinking. I mean I have to again click on textbox to type something
Please help me to find out what the issue is...Any help would be appreciated.
<StackPanel>
<DockPanel>
<TextBlock DockPanel.Dock="Left" Text="ID"/>
<Expander x:Name="IdExp" DockPanel.Dock="Right" IsExpanded="False" ExpandDirection="Down" >
</Expander>
</DockPanel>
<TextBox x:Name="PropertyCCCIDSearch"
Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type UserControl}},
Path=DataContext.SearchCCGId.Value,UpdateSourceTrigger=PropertyChanged}"
Visibility="{Binding ElementName=IdExp, Path=IsExpanded, Converter={x:Static local:Converters.BoolToVisibility}}" >
<TextBox.Style>
<Style>
<Style.Triggers> <DataTrigger Binding="{Binding ElementName=IdExp, Path=IsExpanded}" Value="True">
<Setter Property="FocusManager.FocusedElement" Value="{Binding ElementName=PropertyCCCIDSearch}"/> </DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
</StackPanel>
Your code is working correctly this is what i tried
<Window.Resources>
<BooleanToVisibilityConverter x:Uid="BooleanToVisibilityConverter_1" x:Key="b2v" />
</Window.Resources>
<Grid>
<StackPanel>
<DockPanel>
<TextBlock DockPanel.Dock="Left" Text="ID"/>
<Expander x:Name="IdExp" DockPanel.Dock="Right" IsExpanded="False" ExpandDirection="Down" >
</Expander>
</DockPanel>
<TextBox x:Name="PropertyCCCIDSearch" Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type UserControl}},
Path=DataContext.SearchCCGId.Value,UpdateSourceTrigger=PropertyChanged}"
Visibility="{Binding ElementName=IdExp, Path=IsExpanded,
Converter={StaticResource b2v}}" >
<TextBox.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=IdExp, Path=IsExpanded}" Value="True">
<Setter Property="FocusManager.FocusedElement" Value="{Binding ElementName=PropertyCCCIDSearch}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
</StackPanel>
</Grid>
</Window>
I have a listbox where the itemtemplate is using a style. The styles specifies a border with a datatrigger setting the visibility of the border to collapsed depending on a property. This works fine except I can still see a very narrow line for each item, in the list, that is collapsed. I was hoping someone could help with how to set the visibility so that there are no visible traces as this is quite apparent when consecutive items have been collapsed.
The datatemplate specifies an outer border with a dockpanel inside of this - there are then stackpanels docked to this.
Any help is appreciated.
Well this is a simplified template:
<DataTemplate x:Key="myTemplate">
<Border BorderThickness="0">
<Border.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsActive}" Value="False">
<Setter Property="Border.Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<DockPanel LastChildFill="True" HorizontalAlignment="Stretch">
<StackPanel DockPanel.Dock="Right" HorizontalAlignment="Right" >
<TextBlock Text="{Binding Path=SeqNo, Converter={StaticResource SeqToTextConv}}"/>
<Label Content="..." />
</StackPanel>
</DockPanel>
</Border>
</DataTemplate>
You are succesfully hiding your item, however, the ListBox wraps each of your items within a ListBoxItem, this adds concepts such as selection to your item. I suspect you are still seeing the ListBoxItem in the case where your items are hidden. You can use the ItemContainerStyle to hide ListBoxItems ...
<ListBox>
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsActive}" Value="False">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
This can also be achieved by populating ListBox.Items only with ListBoxItem instead of other controls:
ListBox.Items.Add(new ListBoxItem {
Content = new CheckBox {Content = "item 1"}
})
or
<ListBox>
<ListBox.Items>
<ListBoxItem>
<CheckBox Content="item 1"/>
</ListBoxItem>
</ListBox.Items>
</ListBox>
Then in the code behind or in the trigger, you can hide the items directly:
ListBox.Items[0].Visibility = Visibility.Collapse
This will hide the item as well as the 4px border. This method gives you control of visibility for each individual item.
I went with ColinE's proposed solution. Here is a full snipped for everybody's convenience. Thanks ColienE.
<ListBox ItemsSource="{Binding Properties}" Height="110">
<ListBox.ItemTemplate>
<HierarchicalDataTemplate>
<CheckBox Content="{Binding Name}" IsChecked="{Binding IsSelected}" Visibility="{Binding Visible}" />
</HierarchicalDataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Style.Triggers>
<DataTrigger Binding="{Binding Visible}" Value="Collapsed">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>