WPF Listbox containing Expander controls - wpf

I've been playing around with wpf for a few months with mixed success but this one has me stumped. I have a ListBox containing Expanders, something like this:
<ListBox>
<Expander Header="Options">
<StackPanel>
<CheckBox Content="Option 1" />
<CheckBox Content="Option 2" />
<CheckBox Content="Option 3" />
</StackPanel>
</Expander>
<Expander Header="More Options">
<StackPanel>
<CheckBox Content="Option 1" />
<CheckBox Content="Option 2" />
<CheckBox Content="Option 3" />
</StackPanel>
</Expander>
</ListBox>
I'm trying to figure out how to:
Prevent the content portion of the Expander from changing colour when it is selected in the ListBox. I want only the Expander's header to have a blue background, not the CheckBoxes
Make an Expander the selected item in the ListView when its header is clicked. At the moment you have to click outside of the Expander's header's text to have it become selected in the list view

The solution to your first question is simple. Just add this into the ListBox.Resources:
<ListBox.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent" />
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Transparent" />
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Black" />
<SolidColorBrush x:Key="{x:Static SystemColors.ControlTextBrushKey}" Color="Black" />
</ListBox.Resources>
You are free to change the colours to any that you prefer.
The solution to your second question is far from simple. I should like to say that declaring controls inside a ListBox is far from optimal. A much better solution is to create a data type class, bind a collection of these instances to the ListBox.ItemsSource property and then to create DataTemplates to define what each item should look like... that is where you should declare your Expander controls.
As at StackOverflow, we prefer one question to be asked per post, please try what I have just suggested, searching for the relevant terms online if necessary, and then come back with a new question, showing us your new code.

Related

How to change tab control tab item's header color [MahApps.Metro]

I have a MetroAnimatedSingleRowTabControl from MahApps Metro. I want to change the header's foregorund color from blue (defined by the template) to white.
This is what I have got:
<Grid x:Name="Body" Grid.Row="1" Margin="20,0,20,0">
<controls:MetroAnimatedSingleRowTabControl>
<controls:MetroAnimatedSingleRowTabControl>
<controls:MetroTabItem Header="Server"/>
</controls:MetroAnimatedSingleRowTabControl>
</controls:MetroAnimatedSingleRowTabControl>
</Grid>
I want to let the Server Header to appear in white.
The colors are set in the triggers towards the end of the TabItem template.
Once you got the Keys you can overwrite the resource bindings
<Grid x:Name="Body" Grid.Row="1" Margin="20,0,20,0">
<Controls:MetroAnimatedSingleRowTabControl>
<Controls:MetroAnimatedSingleRowTabControl.Resources>
<SolidColorBrush x:Key="AccentColorBrush" Color="Red"/>
<SolidColorBrush x:Key="HighlightBrush" Color="Orange"/>
</Controls:MetroAnimatedSingleRowTabControl.Resources>
<Controls:MetroTabItem Header="Server"/>
</Controls:MetroAnimatedSingleRowTabControl>
</Grid>

Is there something like a WPF listview without the selection?

The application I'm developing has a kind of accordion made of expanders but each exapnder acts independently rather than only allowing a single open item at a time. Each expander is related to an item in a collection in the view model.
My currently solution is to use a listbox and then bind the lists itemsource to the collection and have an item template render the expander and the exapnders contents.
The problem is that the listbox treats each expander as an item (obviously) and allows selection and highlighting. Highlighting is a little ugly and could be disabled, but the selection causes me some issues because it causes the list to scroll to show as much of the expanded expander as possible.
Is there a WPF control that is a little like a stackpanel (perhaps) that would allow me to bind the contained controls using item templating but without the selection and highlighting?
<ListBox Grid.Row="0" Grid.Column="0" Width="Auto" SelectionMode="Single" ItemsSource="{Binding Path=MeasurementSources}">
<ListBox.ItemTemplate>
<DataTemplate>
<Expander Header="{Binding Name}" IsEnabled="{Binding Available}">
<ListBox Width="Auto" SelectionMode="Single"
ItemsSource="{Binding Path=Measurements}"
SelectedItem="{Binding Path=SelectedMeasurement}">
<ListBox.ItemTemplate>
<DataTemplate>
<WrapPanel>
<TextBlock Text="{Binding Name}" FontWeight="Bold" />
<TextBlock Text=" "/>
<TextBlock Text="{Binding Created}"/>
</WrapPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Expander>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
If you want List-like capabilities without selection capabilities, you should use an ItemsControl - incidentally the base class of Selector which in turn is the base class of ListBox
The whole thing then just becomes
<ItemsControl Width="Auto" ItemsSource="{Binding Measurements}"
<ItemsControl.ItemTemplate>
<DataTemplate>
<WrapPanel>
<TextBlock Text="{Binding Name}" FontWeight="Bold" />
<TextBlock Text=" "/>
<TextBlock Text="{Binding Created}"/>
</WrapPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Obviously, you cannot bind a selected item in this case.
This is a useful piece of information that I had not realised.
http://msdn.microsoft.com/library/windows/apps/hh780657.aspx
Note ItemsControl is the base class for several common collection
controls, including ListView, GridView, FlipView, ListBox, and
ComboBox controls. These examples use the ListView and GridView
controls, but the info applies generally to ItemsControls.
In other words using the ItemsControl really is the way to solve my issue because using a ListBox and then trying to disable the highlight and the selection functionality really is turning it back into it's own base class.
The best solution is for me:
<Style TargetType="{x:Type ListBoxItem}">
<Style.Resources>
<!-- With focus -->
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}"
Color="Transparent" />
<!-- Without focus -->
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}"
Color="Transparent" />
<!-- Text foreground -->
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}"
Color="Black" />
</Style.Resources>
<Setter Property="FocusVisualStyle" Value="{x:Null}"></Setter>
</Style>
and I found it few months ago somwhere on stackoverflow :)

Styling `ListView` menu with round corners

I'm looking to build a menu using a ListView (I'm open to using anything else really that'll achieve the effect I'm looking for. The look I would like to emulate is the following.
Here is what I currently have for my XAML.
<ListView
ItemsSource="{Binding Decisions}"
SelectedItem="{Binding SelectedDecision}"
HorizontalAlignment="Left"
BorderThickness="0"
Width="350"
FontSize="12">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel
Width="{Binding (FrameworkElement.ActualWidth), RelativeSource={RelativeSource AncestorType=ScrollContentPresenter}}" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<Border
BorderThickness="1"
BorderBrush="#DDD"
CornerRadius="2">
<TextBlock
Text="{Binding Converter={StaticResource DecisionTypeNameConverter}}"
Padding="8"
Background="#EEE" />
</Border>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
This produces an alright looking menu until I select an item. Once an item is selected it is surrounded by an ugly dark blue. How can I recreate this look (the gradient effect isn't required) in XAML?
Do you need to track the SelectedItem?
If not, I would suggest using an ItemsControl
If so, you need to overwrite the selected item brush color so it doesn't show up. This is a system color, and I usually overwrite it like this:
<ListView.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent" />
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Transparent" />
</ListView>
In order to prevent the blue selection rectangle you would have to set the ItemContainerStyle instead of the ItemTemplate. Consult the MSDN on ListView Styles and Templates to find out about the ListViewItem default style, especially the "Selected" visual state.

Showing a new Window right next to a DataCell in DataGrid (WPF)

I want a scenario when a user clicks on a cell in DataGrid in WPF, I want to open NumPad next to it (This is basically for touch based input).
The NumPad, I understand is a separate window.
1) How can I know which Cell is selected 2) how can I show the NumPad next to the cell? 3) How can I find the coordinates of cell to position my NumPad? 4) How can I set the value of cell based on NumPad entry?
NumPad is a WPF User Control in the same application.
DataGrid is a .NET 4 Control.
It's a normal Windows Desktop application
This is not a trivial task and you should have some knowledge of WPF to accomplish this, but here are some ideas what you might look for:
The DataGridCell.IsSelected property tells you whether a cell is selected.
I would use a Popup to show the NumPad directly besides the cell.
If you use a Popup you do not need the coordinates, but you can specify the relative placement using the Popup.Placement property. Also see this MSDN document: Popup Placement Behavior
You could try to use a Binding from the NumPad to the user control in the DataGridCell.
Using the DataGrid.CellStyle or the DataGridColumn.CellStyle property you can specify an alternate style for all cells of the DataGrid or some specific column. Within this style, you could change the template and add a Popup which is opened only if the current cell is selected. You can easily achieve this by binding the Popup.IsOpen property to the DataGridCell.IsSelected property.
This is just an initial idea. You will still have to have a look at the provided MSDN links and also read some other stuff about WPF. Although it might take some time to learn this 'WPF way' (i.e. only XAML), it is (in my eyes) much easier than using lots of code-behind to determine the currently selected cell, positioning a control at the correct location, transferring the data from the NumPad to the cell and so on...
I really like Gehho's answer.
Doing as he suggested, besides using the Template column over styling text columns, resulted in the following XAML:
<Grid x:Name="LayoutRoot">
<DataGrid>
<DataGrid.Columns>
<DataGridTextColumn Header="R" Binding="{Binding Color.R}" />
<DataGridTextColumn Header="G" Binding="{Binding Color.G}" />
<DataGridTextColumn Header="B" Binding="{Binding Color.B}" />
<DataGridTextColumn Header="Alpha" Binding="{Binding Color.A}" />
<DataGridTemplateColumn Header="Thumb">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Border x:Name="border" Background="{Binding}">
<Popup IsOpen="{Binding IsMouseOver, ElementName=border, Mode=OneWay}"
PopupAnimation="Fade"
Placement="MousePoint">
<Border Width="200" Height="200" Background="{Binding Background , ElementName=border, Mode=OneWay}" />
</Popup>
</Border>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
<SolidColorBrush Color="Red"/>
<SolidColorBrush Color="Green"/>
<SolidColorBrush Color="Blue"/>
<SolidColorBrush Color="Yellow"/>
<SolidColorBrush Color="SteelBlue"/>
<SolidColorBrush Color="Lime"/>
<SolidColorBrush Color="Cyan"/>
</DataGrid>
</Grid>
</Window>
Hope this helps!

Select whole item in ListBox in WPF [duplicate]

This question already has answers here:
Stretch ListBox Items hit area to full width of the ListBox? ListBox style is set implicity through a theme
(2 answers)
Closed 7 years ago.
I've been googling around for something similar to FullRowSelect for a listview. Currently my listbox items are only selectable if you click on a part of it that is being taken up with content eg a textblock, item etc. This means that the "clickable" area is dependant on how long the entry is, but ideally i'd like to be able to click anywhere within the rectangle that defines each item.
I hope that makes sense
You need to adjust the ItemContainerStyle within the ListBox so that its HorizontalContentAlignment is set as Stretch versus Left. You can still align the content within the ListBoxItem as needed.
<Window.Resources>
<Style x:Key="Stretched" TargetType="{x:Type ListBoxItem}">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</Window.Resources>
<Grid>
<ListBox ItemContainerStyle="{StaticResource Stretched}">
<ListBox.Items>
<ListBoxItem>
<Grid>
<TextBox HorizontalAlignment="Left" Height="25" Width="100"/>
</Grid>
</ListBoxItem>
<ListBoxItem>
<Grid>
<TextBox HorizontalAlignment="Left" Height="25" Width="100"/>
</Grid>
</ListBoxItem>
</ListBox.Items>
</ListBox>
</Grid>

Resources