Expander Header not display group field content, only ItemsCount - wpf

i have a WPF DataGrid with a GroupStyle
<DataGrid.GroupStyle>
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander IsExpanded="True">
<Expander.Header>
<StackPanel>
<TextBlock Text="{Binding Path=citta}" Margin="5,0,0,0" Width="100" FontWeight="Bold"/>
<TextBlock Text="{Binding Path=ItemCount}" />
</StackPanel>
</Expander.Header>
<Expander.Content>
<ItemsPresenter />
</Expander.Content>
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</DataGrid.GroupStyle>
code behind:
var qq = (from a in q select new { formareg = a.Get("formareg"), citta = a.Get("citta"), conteggio = a.Get("conteggio"), parametro = a.Get("idcitta").ToString() + "|" + a.Get("formareg") }).OrderBy(x => x.citta).ToList();
ListCollectionView cv = new ListCollectionView(qq);
cv.GroupDescriptions.Add(new PropertyGroupDescription("citta"));
GrigliaDati.ItemsSource = cv;
All works fine but in Header of each group i see only ItemCount and not Path=citta.
What's wrong??

Same as my earlier answer to this question, it's because you bind to wrong field. You need to bind to group name and not to the field you group by. Try somethink like this:
<TextBlock Text="{Binding Path=Name}">
Each group is a CollectionViewGroup and it has its own properties that you can use when specifying group header.

Related

Bind TextBlock.Text to specific item-property in collection where value matches another binding

Trying to stay on the MVVM road, I keep struggling with the following task for hours:
I want to show the String-value of a specific Item (in a TextBlock), which is part of the UserCollection (ObservableCollection<Tuple<int, string>>). The selection should take place via the Int-property of the item in the Collection, matching the bound IdCreatedByUser-Property in MyOrder.
To make things more clear:
An UserCollection that holds an ID (int) and NAME (string):
public ObservableCollection<Tuple<int, string>> UserCollection;
A MyOrder-Property holding an Instance of the Orders-Class:
public Order MyOrder;
Here an example of the Orders-class.
public class Order: INotifyPropertyChanged
{
public string Comment;
public int IdCreatedByUser;
public bool IsComplete;
}
Please note that this is just an example for the properties..knowing that get,set are missing here..
The only solution I came up with is to hijack a Combox like this:
<ComboBox ItemsSource="{Binding UserCollection}"
DisplayMemberPath="Item2"
SelectedValue="{Binding MyOrder.IdCreatedByUser}"
SelectedValuePath="Item1">
<ComboBox.Template>
<ControlTemplate>
<TextBlock Text="{Binding SelectedItem.Item2,RelativeSource={RelativeSource Mode=TemplatedParent}}" />
</ControlTemplate>
</ComboBox.Template>
</ComboBox>
The fact that I can use ItemsSource, SelectedValue and SelectedValuePath makes it possible for me to select and show the desired Item. Any solutions for the use of TextBlocks with this one?
I was also thinking about a converter or extra property..but maybe you can show me a way to design this in a better way..
Thanks!
This essentially makes your specialized ComboBox easily reusable. Stuff like FontWeight will be inherited by the ContentPresenter.
<Style x:Key="CollectionLookupComboBox" TargetType="ComboBox" BasedOn="{StaticResource {x:Type ComboBox}}">
<!--
Default to readonly, but you can override that for particular instances
if that's useful somewhere.
-->
<Setter Property="IsReadOnly" Value="True" />
<Style.Triggers>
<Trigger Property="IsReadOnly" Value="True">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ComboBox">
<Grid>
<Border
x:Name="OuterBorder"
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="Transparent"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Background="Transparent"
>
<!--
The margin here keeps the text in the same spot when I toggle IsReadOnly,
with the default theme I have. May need to fiddle with that to get it to
look right for you.
-->
<ContentPresenter
Margin="3,2,2,0"
IsHitTestVisible="False"
Content="{TemplateBinding SelectionBoxItem}"
ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"
VerticalAlignment="Stretch"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
/>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
Example -- this is overkill; you don't need an ItemTemplate or boldface, but it demonstrates how all the usual ComboBox stuff is supported:
<StackPanel
Orientation="Vertical"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
>
<CheckBox
x:Name="ReadOnlyCheckBox"
IsChecked="True"
Margin="1"
Content="Read-Only"
/>
<ComboBox
Margin="1"
Style="{StaticResource CollectionLookupComboBox}"
IsReadOnly="{Binding IsChecked, ElementName=ReadOnlyCheckBox}"
MinWidth="80"
SelectedIndex="0"
FontWeight="Bold"
Foreground="Green"
>
<ComboBox.ItemTemplate>
<DataTemplate>
<Border BorderBrush="DeepSkyBlue" BorderThickness="2" CornerRadius="4">
<Label Content="{Binding}" />
</Border>
</DataTemplate>
</ComboBox.ItemTemplate>
<sys:String>First Item</sys:String>
<sys:String>Second Item</sys:String>
</ComboBox>
</StackPanel>

How to orientate chart label with WPF DataVizualization?

I have a column chart but, as you see in the screenshot, the labels are overlapping. I'd like to display them vertically or in oblique.
Here's the actual horrible result:
Here's the xaml I wrote:
<dvc:Chart Margin="4">
<dvc:ColumnSeries Title="Ticket count by department"
ItemsSource="{Binding Tickets, Converter={StaticResource GroupChartConverter}}"
IndependentValueBinding="{Binding Item1}"
DependentValueBinding="{Binding Item2}">
</dvc:ColumnSeries>
</dvc:Chart>
I found solution using template or code behind but they use so many lines of code for a not so clean result. I'm sure it's just a matter of one or two lines of code but Google is not so talkative about this...
What is wrong with using a template?
<dvc:Chart Margin="4">
<dvc:ColumnSeries Title="Ticket count by department"
ItemsSource="{Binding Tickets, Converter={StaticResource GroupChartConverter}}"
IndependentValueBinding="{Binding Item1}"
DependentValueBinding="{Binding Item2}">
<dvc:ColumnSeries.IndependentAxis>
<dvc:CategoryAxis
Orientation="X">
<dvc:CategoryAxis.AxisLabelStyle>
<Style TargetType="dvc:AxisLabel">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="dvc:AxisLabel">
<TextBlock Text="{TemplateBinding FormattedContent}">
<TextBlock.LayoutTransform>
<RotateTransform Angle="-90"/>
</TextBlock.LayoutTransform>
</TextBlock>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</dvc:CategoryAxis.AxisLabelStyle>
</dvc:CategoryAxis>
</dvc:ColumnSeries.IndependentAxis>
</dvc:ColumnSeries>
</dvc:Chart>

Expander inside ListViewItem

I have a listview for which i have implemented grouping and have defined an expander inside the groupstyle as shown below :
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Margin" Value="0,0,0,5"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander IsExpanded="True" >
<Expander.Header>
<DockPanel>
<TextBlock FontWeight="Bold" Text="{Binding Path=Name}" Margin="5,0,0,0" Width="100"/>
<TextBlock FontWeight="Bold" Text="{Binding Path=ItemCount}"/>
<TextBlock FontWeight="Bold" Text=" Items"/>
</DockPanel>
</Expander.Header>
<Expander.Content>
<ItemsPresenter />
</Expander.Content>
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</ListView.GroupStyle>
I want to modify the expander such that only one is expanded and the rest are collapsed if more than one are there and also if i want to programmatically expand any one of the expanders i.e. suppose i add an object from cs and want to show that expander opened, it should be possible, any suggestions ??
Thanks in advance
Edit : The code to bind the listview and the group :
CollectionViewSource viewSource = new CollectionViewSource { Source = TO_DOlst };
viewSource.GroupDescriptions.Add(new PropertyGroupDescription("timeCategory"));
lstView.ItemsSource = viewSource.View;
timecategory is a member of the class
You can Bind IsExpanded property by creating a boolean property in your class just like Name and define all Business rules in CS directly.
if(ItemsSource.Count() > 1)
//set IsExpanded = false;
else
// set only first item and so on.
Regards.

Closing TabItem by clicking middle button

I have a problem.
In my WPF application, if i press a tabItem with middle mouse button, this tabItem should close. Just like in FireFox.
But I try to do this using MVVM, and i need to use commands. Also my tabItems are created dynamically.
Help me plz!
Thank you!
Create a DataTemplate for your tab items like this:
<DataTemplate x:Key="ClosableTabTemplate">
<Border>
<Grid>
<Grid.InputBindings>
<MouseBinding Command="ApplicationCommands.Close" Gesture="MiddleClick" />
</Grid.InputBindings>
<!-- the actual contents of your tab item -->
</Grid>
</Border>
</DataTemplate>
In your application window, add a the close command
<Window.CommandBindings>
<CommandBinding Command="ApplicationCommands.Close" Executed="CloseCommandExecuted" CanExecute="CloseCommandCanExecute" />
</Window.CommandBindings>
and finally assign the data template as item template to your tab control.
You could add a MouseBinding to some InputBindings perhaps?
Closing a TabItem (Not Selected) - TabControl
<TabControl x:Name="TabControlUser" ItemsSource="{Binding Tabs}" Grid.RowSpan="3">
<TabControl.Resources>
<Style TargetType="TabItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TabItem">
<Border Name="Border" BorderThickness="1,1,1,0" BorderBrush="Gainsboro" CornerRadius="4,4,0,0" Margin="2,0">
<ContentPresenter x:Name="ContentSite"
VerticalAlignment="Center"
HorizontalAlignment="Center"
ContentSource="Header"
Margin="10,2"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Border" Property="Background" Value="LightSkyBlue" />
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Setter TargetName="Border" Property="Background" Value="GhostWhite" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</TabControl.Resources>
<TabControl.ItemTemplate>
<!-- this is the header template-->
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Header}" FontWeight="ExtraBold" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<Image Source="/Images/RedClose.png" Width="22" Height="22" MouseDown="Image_MouseDown" HorizontalAlignment="Right" Margin="10 0 0 0"/>
</StackPanel>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<!-- this is the body of the TabItem template-->
<DataTemplate>
<UserControl Content="{Binding UserControl, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
C# Code - Image MouseDown Click Event
try
{
int matches = 0;
DependencyObject dependency = (DependencyObject)e.OriginalSource;
// Traverse the visual tree looking for TabItem
while ((dependency != null) && !(dependency is TabItem))
dependency = VisualTreeHelper.GetParent(dependency);
if (dependency == null)
{
// Didn't find TabItem
return;
}
TabItem selectedTabItem = dependency as TabItem;
var selectedTabContent = selectedTabItem.Content as MainWindowViewModel.TabItem;
foreach (var item in MainWindowViewModel.Tabs)
{
if (item.Header == selectedTabContent.Header)
{
matches = MainWindowViewModel.Tabs.IndexOf(item);
}
}
MainWindowViewModel.Tabs.RemoveAt(matches);
}
catch (Exception ex)
{
System.Windows.Application.Current.Dispatcher.Invoke((System.Action)(() => new View.MessageBox(ex.Message).ShowDialog()));
}
This event finds with the exact Mouse clicked position (as TabItem)and this will remove
MainWindowViewModel.Tabs.RemoveAt(matches); the TabItem(even if it is not selected).

Data Binding with Silverlight accordion Control

I have Silverlight Accordion control in the ChildWindow and I customized it the following way
<Style x:Key=itemStyle TargetType=AccordionItem>
<Setter Porperty=HeaderTemplate>
<DataTemplate>
<TextBlock x:Name=_headertext/>
</DataTemplate>
</Setter>
</Style>
<Accordion Style"{StaticResource itemStyle}">
<Accordion.ContentTemplate>
<DataTemplate>
<StackPanel>
<CheckBox/>
<TextBlock x:name=_contenttext/>
</DataTemplate>
<Accordion.ContentTemplate>
</Accordion>
Now I have a method in my Chilwindow.Xaml
public void LoadItems(ObservableColection<Groups> gp)
{}
This method is called from the mainpage and it passes the gp value
Groups is a class with public properties and Observable collections.For example
public class Groups
{
public string FirstName{get, set;}
public ObservableCollection<Details> details {get, set;}
public Groups()
{
this.details=new ObservableCollection<Details>();
}
}
My Details Class is as follows
public class Details
{
public int id {get; set;}
public string LastName{get; set;}
--------
-------
}
Now I have to bind the _headertext(TextBlock in header Template) with the FirstName and _contenttext(TextBlock in Content Template) with LastName.
Please help me in doing this.I need your help.
Thanks
Rani
Why not use databinding in XAML directly? You should not need to do this in code.
<Style x:Key=itemStyle TargetType=AccordionItem>
<Setter Porperty=HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding FirstName}"/>
</DataTemplate>
</Setter>
</Style>
<Accordion Style"{StaticResource itemStyle}">
<Accordion.ContentTemplate>
<DataTemplate>
<StackPanel>
<CheckBox/>
<TextBlock Text="{Binding LastName}"/>
</DataTemplate>
<Accordion.ContentTemplate>
</Accordion>
First, the TargetType is pointed at AccordionItem and you are trying to use the style on the Accordion element itself. This will never work. In order to get this to work, you will need to create two styles, one for the Accordion itself and one for the AccordionItem that you reference within the style for the accordion.
<Style x:Key="itemStyle" TargetType="layoutToolkit:AccordionItem">
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="{Binding Header}"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="accordionStyle" TargetType="layoutToolkit:Accordion">
<Setter Property="ItemContainerStyle" Value="{StaticResource itemStyle}" />
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="{Binding Content}"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
Then you define your accordion control like such:
<layoutToolkit:Accordion Height="Auto"
Name="accordion1"
ExpandDirection="Right"
SelectionMode="One"
ItemsSource="{Binding}"
Style="{StaticResource accordionStyle}">
</layoutToolkit:Accordion>

Resources