I am having a design problem and I know there has to be a way to make it work. I tried the solutions here: Annoying auto scroll of partially displayed items in WPF ListView
But they didnt work for me because I am not allowed to work in the code-behind.
I have a list of items from a wpf ListBox. like this:
when I try to select the CheckBox in line 5, the Window centers on it but does not check it. After further testing, I found that it will not select the CheckBox as long as the bottom border of the item is not in view.
Here is the xaml for the ListBox and its Style:
<ListBox Grid.Column="0" Grid.Row="1" Name="RequestCheckoutV"
ItemsSource="{Binding Path=CheckoutVM, Mode=TwoWay, IsAsync=True}"
SelectedItem="{Binding Path=SelectedPermit}"
BorderThickness="0"
KeyboardNavigation.TabNavigation="Continue">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="KeyboardNavigation.IsTabStop" Value="False" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="Control.HorizontalContentAlignment" Value="Center"/>
<Setter Property="Control.VerticalContentAlignment" Value="Top"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}" >
<ContentPresenter />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
What can I do to make this select the checkbox instead of just centering it?
Any help is appreciated.
So by adding the specification of "Press" to ClickMode property to CheckBox via ClickMode="Press" you're telling that object to basically ignore the event otherwise hijacked by the list item template. Now it will accept the first event in it's hit area for itself instead of the list item since it's default is "Release". Cheers :)
Try adding to your .ItemContainerStyle:
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Style.Triggers>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="IsSelected" Value="True"></Setter>
</Trigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
This will effectively give focus to anything you click in there.
Related
I have a listbox in WPF, and when they select an item, it shows an ugly colors
Can I make all the items non-selectable?
If you don't need selection, use an ItemsControl rather than a ListBox
Add Focusable property as false in ListBoxItem style:
<Style x:Key="{x:Type ListBoxItem}" TargetType="{x:Type ListBoxItem}">
<!-- Possibly other setters -->
<Setter Property="Focusable" Value="False" />
</Style>
Please use this inside your listbox. I found this very elegant solution
<ListBox ItemsSource="{Binding YourCollection}">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Focusable" Value="False"/>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
If you dont want them selectable then you probably dont want a listview.
But if this is what you really need then you can do it with a style:
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Page.Resources>
<Style x:Key="{x:Type ListBoxItem}" TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border
Name="Border"
Padding="2"
SnapsToDevicePixels="true">
<ContentPresenter />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter TargetName="Border" Property="Background" Value="#DDDDDD"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="#888888"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Page.Resources>
<Grid>
<ListBox>
<ListBoxItem>One</ListBoxItem>
<ListBoxItem>Two</ListBoxItem>
<ListBoxItem>Three</ListBoxItem>
</ListBox>
</Grid>
</Page>
Look at the IsSelected Trigger. You can make the border a different colour so it is not "Ugly" or set it to transparent and it will not be visible when selected.
Hope this helps.
There's an even easier way: set ListBox property IsHitTestVisible="False". This prevents all the items in the list from receiving mouse events. This has the advantage of stopping the highlighting as you mouse-over as well.
It works for me in WP 7.1.
A simple way to do this (using the answer from viky above) is to set the selected index to -1 in the SelectionChanged(), as follows.
public void OnListView_SelectionChanged(Object sender, RoutedEventArgs e)
{
if (null != sender && sender is ListView)
{
ListView lv = sender as ListView;
lv.SelectedIndex = -1;
}
}
Better to avoid events, it's more elegant and without side effects the Style tag.
<ListBox>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="IsEnabled" Value="False"/>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
... what you want as a source ...
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
you can handle SelectionChanged event of ListBox and unselect the selected item in the event handler.
You can also make disabled Listbox, which will give you static, non-interactive listbox.
<ListBox IsEnabled="False"/>
I think this is the solution as simple as possible.
In my case I had templated ListboxItems with a Textblock and a ComboBox. The only "active" should be the Combo...
<ScrollViewer VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="Disabled"
CanContentScroll="True" />
<ItemsControl>
....here my content....
</Itemscontrol>
</ScrollViewer>
did work for me as expected.
BR,
Daniel
You can also handle PreviewMouseDown event
And to prevent tap you can set KeyboardNavigation.TabNavigation="None"
<ListView x:Name="Cards"
.....
PreviewMouseDown="CardMonthsDescriptors_OnPreviewMouseDown"
KeyboardNavigation.TabNavigation="None"
>
...
private void Cards_OnPreviewMouseDown(object sender, MouseButtonEventArgs e)
{
e.Handled = true;
}
Problem
I have a WPF ListView with a GridView as ListView.View in order to have columns in my ListView. In my code, I am changing the SelectedIndex property (bound to an int in my ViewModel) in order to change the selection index. But doing this results in a outline box (see pic) around the previously selected item. Due to visual style I want to remove this outline or move it to the new selected item.
What I have already tried
I already tried changing the ControlTemplate of the ListViewItem (code below)
<ControlTemplate TargetType="{x:Type ListViewItem}">
<Border Background="{TemplateBinding Background}">
<GridViewRowPresenter Margin="2" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"/>
<Border.InputBindings>
<MouseBinding MouseAction="LeftDoubleClick" Command="{Binding ...}"/>
</Border.InputBindings>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#D9EBF9"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="False">
<Setter Property="Background" Value="Transparent"/>
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="#CCE8FF"/>
</Trigger>
</ControlTemplate.Triggers>
I also searched for other solutions online, but I wasn't able to find a solution that worked for me.
Answer
Thanks #dymanoid
Setting FocusVisualStyle to {x:Null} in the style of the ListViewItem solved by problem.
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
I wanted to restyle my buttons to be more flat so I have created two styles; first for ToggleButton that derives from ToolBar.ToggleButtonStyleKey and second for Buttonthat derives from ToolBar.ButtonStyleKey.
It worked great - the buttons are now toolbar-like and flat. Second thing I wanted is to have Background property to be transparent when user hovers the cursor over the control. So to achieve that I defined a simple trigger that sets the Background to Transparent on IsMouseOver event. It worked for ToggleButton, however, the same trigger didn't work for Button(the background was not affected at all).
Does anyone know why this trigger works great for ToggleButton and does not work for Button? I did expect the same behavior since both styles are from the same family.
Below is the full code.
<Window x:Class="WpfButtonsTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style x:Key="FlatToggleButton" TargetType="ToggleButton"
BasedOn="{StaticResource {x:Static ToolBar.ToggleButtonStyleKey}}">
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Focusable" Value="False"/>
<Setter Property="Background" Value="Transparent"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Transparent"/>
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="FlatButton" TargetType="Button"
BasedOn="{StaticResource {x:Static ToolBar.ButtonStyleKey}}">
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Focusable" Value="False"/>
<Setter Property="Background" Value="Transparent"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Transparent"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<StackPanel>
<ToggleButton Style="{StaticResource FlatToggleButton}">
I am Toggle Button
</ToggleButton>
<Button Style="{StaticResource FlatButton}">
I am Button
</Button>
</StackPanel>
</Grid>
</Window>
I had a look using Snoop (a very handy program for inspecting WPF ) and it looks like the template which you're using as a basis, ToolBar.ButtonStyleKey, has a trigger which selects a solid Brush for the background of a Border element within the Button (in thise case when IsMouseOver is true).
Your local style trigger is successfully setting the background of the Button element to transparent (or rather, keeping it transparent), but the Border background is unaffected, so you'll still see the highlighting behaviour.
Border Background:
Button Background:
I think you'll have to define a ControlTemplate to get the button you're after, I've grabbed this from one of the ToolBar samples included in Kaxaml (a nice XAML editor). It's a reasonable facsimile of the Toolbar bas button style, with a few bits removed, it may behave as you want, or you might need to tweak it depending on your desired behaviour.
I've left the IsPressed trigger in place, you may want to remove it, or add additional triggers.
<Style x:Key="ToolBarButtonBaseStyle" TargetType="{x:Type ButtonBase}">
<Setter Property="SnapsToDevicePixels" Value="true"/>
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ButtonBase}">
<Border
x:Name="Border"
BorderThickness="1"
Background="Transparent"
BorderBrush="Transparent">
<ContentPresenter
Margin="2"
HorizontalAlignment="Center"
VerticalAlignment="Center"
RecognizesAccessKey="True"/>
</Border>
<ControlTemplate.Triggers>
<!-- Additional triggers removed, e.g "IsMouseOver" -->
<!-- You may not want any at all -->
<Trigger Property="IsPressed" Value="true">
<Setter TargetName="Border" Property="Background" Value="#E0E0E0" />
<Setter TargetName="Border" Property="BorderBrush" Value="#606060" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I see that the both FlatToggleButton and FlatButton styles already have Background as Transparent
<Setter Property="Background" Value="Transparent"/>
When the triggers is fired on IsMouseOver and set the Background again to Transparent you will not see any difference
So what you need to do is one of these options :
Change both styles so that the Background is something else than Transparent
Change the trigger so it sets the Background to something else than Transparent
I'm trying to customize my ToggleButtons so that when checked they say 'Yes' in green and when not checked, say 'No' in red.
I've created the following style which is sitting in my Styles resource dictionary.
<!-- ToggleButtons -->
<Style x:Key="YesNoToggleStyle" TargetType="ToggleButton">
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Background" Value="SpringGreen" />
<Setter Property="Content">
<Setter.Value>
<TextBlock Text="Yes"/>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsChecked" Value="False">
<Setter Property="Background" Value="Crimson" />
<Setter Property="Content">
<Setter.Value>
<TextBlock Text="No"/>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
This works ... sort of. If the ToggleButton is the last one of either value, then it displays correctly. All previous buttons with the same value are blank. The height was also shrinking, but I fixed that with the 'Height' Setter above the triggers. To illustrate, when a new record is being created it looks like:
and after I've clicked buttons 1, 2, and 3 and 1 again:
I originally had the style referenced from the surrounding grid:
<Grid>
...
<Grid.Resources>
<Style BasedOn="{StaticResource YesNoToggleStyle}" TargetType="{x:Type ToggleButton}" />
</Grid.Resources>
But changing that so each ToggleButton references the style individually (<ToggleButton Style="{StaticResource YesNoToggleStyle}" ... />) hasn't made a difference.
I looked at Customizing the toggle state of a toggle button in wpf, and Override ToggleButton Style where the effect is the same, but they talk about external images, and my issues is all within wpf.
I also looked at the second answer to: i want to change backcolor of toggle button when toggle button ischecked and viceversa in WPF but a) I only have the blend + sketchflow preview that comes with VS2012, and b) i'm a total noob with blend and can't get from Select the "Checked State" to Reset the Background Color instruction in the answer (plus i'd be surprised if this task requires the blend tool).
Can anyone show me what to do to get multiple ToggleButtons to use the same style properly?
This works for me. Somewhere in Dictionary1.xaml:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="YesNoToggleStyle" TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource {x:Static ToolBar.ToggleButtonStyleKey}}">
<Style.Triggers>
<Trigger Property="IsChecked" Value="False">
<Setter Property="Background" Value="Crimson" />
<Setter Property="Content" Value="No"/>
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Background" Value="SpringGreen" />
<Setter Property="Content" Value="Yes"/>
</Trigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
Note, that style is based on ToolBar.ToggleButtonStyle.
<Grid>
<Grid.Resources>
<ResourceDictionary Source="pack://application:,,,/Dictionary1.xaml"/>
</Grid.Resources>
<ItemsControl ItemContainerStyle="{StaticResource YesNoToggleStyle}">
<ToggleButton />
<ToggleButton />
<ToggleButton />
</ItemsControl>
</Grid>
try to replace Content property to ContentTemplate:
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="Yes"/>
</DataTemplate>
</Setter.Value>
</Setter>
In my case I wanted to have a "Locked" ToggleButton in a common dll defined and reused across my Apps.
Here's my result, which worked for me. Maybe someone find it useful (put this in a Resourcedictionary.xaml):
<BitmapImage x:Key="LockedLock"
UriSource="/...;component/Resources/Lock_closed_16p.png" />
<BitmapImage x:Key="OpenLock"
UriSource="/...;component/Resources/Lock_open_16p.png" />
<Style x:Key="LockButton"
TargetType="ToggleButton">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Image Source="{DynamicResource OpenLock }"
Width="12"
Height="12"
Name="contentimage" />
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=ToggleButton , AncestorLevel=1, Mode=FindAncestor }, Path=IsChecked}"
Value="True">
<Setter Property="Image.Source"
TargetName="contentimage"
Value="{DynamicResource LockedLock }" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
Credits to:
Setting Button's Content to <Image> via Styles
Setter Target Name not recognized
I am using Windows 7 and the current item selection (by default) is to paint the background with cornflower blue. Is it possible to get rid of this and replace it with a 1px outline/border over the listview item that the mouse is over?
I basically want to draw a 1px outline/border over any listview item with 1 pixel spacing between the listview item and the outline/border.
I am using a WrapPanel with an Image in it for each item.
Use ItemContainerStyle to override the default background behaviour, and in your style, use a trigger on IsMouseOver to show your outline (for example by having a Setter for BorderThickness).
EDIT: Rough example (not tested):
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border Background="White" BorderThickness="5" Name="Bd">
<Border.Style>
<Style TargetType="Border">
<Setter Property="BorderBrush" Value="White" />
</Style>
</Border.Style>
<ContentPresenter />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Bd" Property="BorderBrush" Value="HotPink" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>