ListBoxItem selection on TextBox focus - wpf

I have a ListBox showing items using the following DataTemplate:
<DataTemplate x:Key="PersonTemplate" DataType="{x:Type DAL:ResultItem}" >
<StackPanel Width="280" >
<TextBox BorderThickness="0" IsReadOnly="True" Background="Transparent" Text="{Binding FullName1, Mode=OneWay}"/>
...
</StackPanel>
</DataTemplate>
I am using a transparent, read-only, borderless TextBox as opposed to a TextBlock because I want users to be able to select the text for copying. Should I do it differently?
How can I write this so that when the user clicks on the TextBox, the ListBoxItem gets selected as well?
Thanks!

I found that the answer is just to do this from the ListBoxItem standpoint, adding the following to its DataTemplate:
<Style.Triggers>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="IsSelected" Value="True"/>
</Trigger>
</Style.Triggers>

Related

How to enable a popup control in wpf when I click inside a textbox?

This is something I want to add as a feature. I've already made e a class that saves the last user search text into a .txt file. I also have it to when the user opens my application the list of searches get loaded into a list. However, what I need help with is displaying this list my xaml.
What I want to achieve for the user is when he/she clicks inside the search box, I want to load the list last saved searches. I wanted it to show up in a ListView inside a Popup control just below the search box. This is how I have my xaml set up
<TextBox Grid.Column="1"
Width="100"
Name="TextBox"
Text="{Binding SearchText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<TextBox.Resources>
<Style TargetType="{x:Type Popup}">
<Style.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="IsOpen" Value="True" />
</Trigger>
<Trigger Property="IsFocused" Value="False">
<Setter Property="IsOpen" Value="False" />
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Resources>
</TextBox>
<Popup Name="SavedSearchesList">
<ListView ItemsSource="{Binding SavedSearchesList, Mode=OneWay}"
SelectedItem="{Binding SavedSearchSelected, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
</ListView>
</Popup>
However when I click inside the Text Box my popup control is not opening. What am I doing wrong? Many thanks in advance.
Remove the Trigger from the TextBox and try the following for your Popup:
<Popup Name="SavedSearchesList" IsOpen="{Binding IsFocused, ElementName=NameofTextBox}">
<ListView ItemsSource="{Binding SavedSearchesList, Mode=OneWay}"
SelectedItem="{Binding SavedSearchSelected, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}">
</ListView>
</Popup>
Keep in mind that you have to set a name for your TextBox and replace 'NameofTextBox' with that name.
Hope this works.

Excess border selection in WPF's Lisbox [duplicate]

I have a ListBox in which each item is a StackPanel. The StackPanel consist of an Image and a TextBlock below it:
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="10">
<Image>
<Image.Source>
<BitmapImage UriSource="{Binding Path=ImageFilePath}"/>
</Image.Source>
</Image>
<TextBlock Text="Title" TextAlignment="Center"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
It looks like this:
When the user select an item, I get the default blue rectangle that surround the StackPanel:
Now, I want to make a different border for the selected-item, but I want it to surround only the image.
I know how to make a control template and put a custom border around the ContentPresenter, but this, of course, will surround the whole StackPanel, not only the Image.
I don’t know if making changes to the ContentPresenter is possible, and if it is a good idea at all. If there is other way to achieve the look I want, it will be fine as well.
Right, the ListBox's own ContentPresenter isn't helpful for what you're doing. You want to a) eliminate the ListBox's own selection visuals and b) replace them with something more suitable in the DataTemplate for your items.
The default selection visual is applied by the default template for ListBoxItem. So replace that template. Using a Style in the resources for your ListBox, apply your own control template to ListBoxItem. Not much to it, just present the content and don't provide a selection background. Then you handle the selection visuals with a trigger in your data template, where your image and your label are defined and you can apply changes to one and not the other. The below example works for me.
Note that there's some fiddling with the HorizontalAlignment on the Border element to make it cling to the Image element within it. Also, I wrote a quickie test viewmodel whose Items property is called Items; I assume this is not the name of the collection member you're using to populate your own ListBox.
<ListBox
Margin="8"
ItemsSource="{Binding Items}"
>
<ListBox.Resources>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Grid>
<ContentPresenter />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.Resources>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Border
x:Name="HighlightBorder"
BorderThickness="4"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Margin="10"
>
<Border.Style>
<Style TargetType="Border">
<!-- MUST set default BorderBrush via a style, if you set it at all.
As an attribute on the Border tag, it would override the effects of
the trigger below.
-->
<Setter Property="BorderBrush" Value="Transparent" />
</Style>
</Border.Style>
<Image Source="{Binding ImageFilePath}" />
</Border>
</Grid>
<DataTemplate.Triggers>
<DataTrigger
Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=ListBoxItem}}"
Value="True">
<Setter TargetName="HighlightBorder" Property="BorderBrush" Value="Orange" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

How to set the Control Visibilty of the Second Control depending on the Binding Value of the first

I have a Custom Wpf Control i.e. combobox:WpfTwComboBox. I want to set the visibility using a property called DisableProviderSelector.
The usual use of triggers is not helping. The scenario here is when the above control i.e. WindowsFormsHost is made visible or collapsed, I want the opposite to happen to the below custom control.
<StackPanel Grid.Row="3" Grid.Column="2" Height="25" Orientation="Horizontal"
Width="375" HorizontalAlignment="Left">
<WindowsFormsHost Height="25" Width="375">
<WindowsFormsHost.Style>
<Style TargetType="WindowsFormsHost">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=DisableProviderSelector}" Value="true">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=DisableProviderSelector}" Value="false">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</WindowsFormsHost.Style>
<commonControls:ProviderSelectorControl RequiredLevel="Save" ModifiedByUser="providerSelectorControl1_ModifiedByUser" x:Name="providerSelectorControl1"/>
</WindowsFormsHost>
<combobox:WpfTwComboBox x:Name="PortalProviderSelector"
SelectedValue="{Binding SelectedPortalProvider}"
ItemsSource="{Binding Path=PortalProvidersCollection}"
DisplayMemberPath="FullName" Width="350" Height="25"
RequiredLevelFlag="Save">
</combobox:WpfTwComboBox>
</StackPanel>
Can anyone please help me on how to set the visibility here?
So DisableProviderSelector is a bool when set to True WindowsFormsHost needs to be Collapsed and ComboBox needs to be Visible. Reverse when bool is false.
So as far as the ComboBox is concerned if bool is True it's Visible and when False it's Collapsed. Thus just bind the ComboBox directly to the Property and use a BooleantoVisibilityConverter
xaml:
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</Window.Resources>
...
<combobox:WpfTwComboBox x:Name="PortalProviderSelector"
Width="350"
Height="25"
DisplayMemberPath="FullName"
ItemsSource="{Binding Path=PortalProvidersCollection}"
RequiredLevelFlag="Save"
Visibility="{Binding DisableProviderSelector,
Converter={StaticResource BooleanToVisibilityConverter}}"
SelectedValue="{Binding SelectedPortalProvider}" />

Set properties of text box when combobox selection is made WPF XAML

how to Set properties of text box when combobox selection is made . foe example set background and IsEnabled property of text box when a combo box selection is made. I want it Purely in XAML not in code behind. i use MVVM
How to enable textBox1 only when SelectedItems is 1
<TextBox Height="23" HorizontalAlignment="Left" Margin="246,177,0,0" Name="textBox2" VerticalAlignment="Top" Width="120">
<TextBox.Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="IsEnabled" Value="False"></Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=comboBox1, Path=SelectedIndex}" Value="1">
<Setter Property="Background" Value="Green"></Setter>
<Setter Property="IsEnabled" Value="True"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
<ComboBox Height="22" HorizontalAlignment="Left" Margin="246,119,0,0" Name="comboBox1" VerticalAlignment="Top" Width="120" />
I think only with XAML you cannot achieve the condition Value ="1" or "3", i.e. a relation in a data trigger more complex than a equality.
For this case you need a converter.
This link could help you
How to get DataTemplate.DataTrigger to check for greater than or less than?
You can use a datatrigger for combo's selected object. Have a look to this previous question: WPF Visibility of a UI element based on combo selection
Try to generate a trigger when selecteditem is {x:Null}. For that, you will need to put your controls inside a DataTemplate and the put the trigger in the template's triggers collection.
Here is a sample code (not tested, please check by your own):
<TextBox Height="23" HorizontalAlignment="Left" Margin="246,177,0,0" Name="textBox2" VerticalAlignment="Top" Width="120" IsEnabled" Value="True" />
<ComboBox Height="22" HorizontalAlignment="Left" Margin="246,119,0,0" Name="comboBox1" VerticalAlignment="Top" Width="120" />
<DataTemplate.Triggers>
<Trigger SourceName="comboBox1" Property="ComboBox.SelectedItem" Value="{x:Null}">
<Setter TargetName="textbox2" Property="TextBox.IsEnabled" Value="False" />
</Trigger>
</DataTemplate.Triggers>

How can I indicate in an Expander header that collapsed contents have an error

I have expanders that contain text boxes, the text boxes use the wpf validation stuff to draw a red box around them ( text boxes are wrapped in Adorner Decorators to make sure I don't get empty red boxes everywhere when the expanders are collapsed)
I want to indicate in the header of the expander that it has contents that have errors (in case it is in a collapsed state) - an icon or red exclamation mark or something. I think I see a way to do this in code from my validation function (not ideal) but is there a way to do it in xaml? Can I use a style for the expander with a trigger somehow pointing to the Validation.HasError of all children?
thanks for any thoughts..
Trev
If you know the contents of your expander, you can use a MultiDataTrigger to do this:
<Expander>
<Expander.Header>
<TextBlock>
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Text" Value="ERROR"/>
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding ElementName=txtWidth, Path=(Validation.HasError)}" Value="False"/>
<Condition Binding="{Binding ElementName=txtHeight, Path=(Validation.HasError)}" Value="False"/>
</MultiDataTrigger.Conditions>
<Setter Property="Text" Value="NO ERROR"/>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</Expander.Header>
<StackPanel>
<TextBox x:Name="txtWidth" Text="{Binding Width, ElementName=rect, UpdateSourceTrigger=PropertyChanged, ValidatesOnExceptions=True}"/>
<TextBox x:Name="txtHeight" Text="{Binding Height, ElementName=rect, UpdateSourceTrigger=PropertyChanged, ValidatesOnExceptions=True}"/>
<Rectangle x:Name="rect" Width="100" Height="100" Margin="10" Fill="Green"/>
</StackPanel>
</Expander>
If the contents of the expander aren't known, then you'll probably have to set Binding.NotifyOnValidationError on the TextBoxes and handle the Error attached event.

Resources