First of all i want to apologize, because i don't know how to ask the question the right way.
I'm not sure how to describe the problem i have.
There is a page in my wpf-application where i draw some lineseries on a chart.
<Page x:Class="Zentralvakuum_Archivauswertung.Views.Zentrale"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Zentralvakuum_Archivauswertung.Views"
xmlns:DV="clr-namespace:System.Windows.Controls.DataVisualization;assembly=System.Windows.Controls.DataVisualization.Toolkit"
xmlns:DVC="clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=System.Windows.Controls.DataVisualization.Toolkit"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
mc:Ignorable="d"
DataContext="{Binding Source={StaticResource ViewModelLocator}, Path=ZentraleVm}"
d:DesignHeight="300" d:DesignWidth="300"
Title="Zentrale">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<DVC:Chart Name="Chart" Width="auto" Height="auto" Title="Something" grid.row="0">
<DVC:Chart.Series>
<DVC:LineSeries Title="1"
IndependentValueBinding="{Binding Path=Key}"
DependentValueBinding="{Binding Path=Value}" ItemsSource="{Binding Istwerte1Liste, UpdateSourceTrigger=PropertyChanged}" >
<DVC:LineSeries.DataPointStyle>
<Style TargetType="DVC:LineDataPoint">
<Setter Property="Template" Value="{x:Null}" />
<Setter Property="Background" Value="Black"/>
<Setter Property="Opacity" Value="0" />
</Style>
</DVC:LineSeries.DataPointStyle>
</DVC:LineSeries>
<DVC:LineSeries Title="1a"
IndependentValueBinding="{Binding Path=Key}"
DependentValueBinding="{Binding Path=Value}" ItemsSource="{Binding Sollwerte1Liste, UpdateSourceTrigger=PropertyChanged}">
<DVC:LineSeries.DataPointStyle>
<Style TargetType="DVC:LineDataPoint">
<Setter Property="Template" Value="{x:Null}" />
<Setter Property="Background" Value="Green"/>
<Setter Property="Opacity" Value="0" />
</Style>
</DVC:LineSeries.DataPointStyle>
</DVC:LineSeries>
<DVC:LineSeries Title="2"
IndependentValueBinding="{Binding Path=Key}"
DependentValueBinding="{Binding Path=Value}" ItemsSource="{Binding Istwerte2Liste, UpdateSourceTrigger=PropertyChanged}" >
<DVC:LineSeries.DataPointStyle>
<Style TargetType="DVC:LineDataPoint">
<Setter Property="Template" Value="{x:Null}" />
<Setter Property="Background" Value="Blue"/>
<Setter Property="Opacity" Value="0" />
</Style>
</DVC:LineSeries.DataPointStyle>
</DVC:LineSeries>
<DVC:LineSeries Title="2a"
IndependentValueBinding="{Binding Path=Key}"
DependentValueBinding="{Binding Path=Value}" ItemsSource="{Binding Sollwerte2Liste, UpdateSourceTrigger=PropertyChanged}">
<DVC:LineSeries.DataPointStyle>
<Style TargetType="DVC:LineDataPoint">
<Setter Property="Template" Value="{x:Null}" />
<Setter Property="Background" Value="Red"/>
<Setter Property="Opacity" Value="0" />
</Style>
</DVC:LineSeries.DataPointStyle>
</DVC:LineSeries>
</DVC:Chart.Series>
</DVC:Chart>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" HorizontalAlignment="Center">
<Label DockPanel.Dock="Top" HorizontalAlignment="Center" FontWeight="Bold" FontSize="20" Content="Start:"/>
<xctk:DateTimePicker Value="{Binding Start, UpdateSourceTrigger=PropertyChanged}" Format="FullDateTime" ShowDropDownButton="False" HorizontalContentAlignment="Center"/>
<Button Content="Actualize" Command="{Binding ActualizeCommand}"/>
</StackPanel>
<StackPanel Grid.Column="1" HorizontalAlignment="Center">
<Label DockPanel.Dock="Top" HorizontalAlignment="Center" FontWeight="Bold" FontSize="20" Content="Ende:"/>
<xctk:DateTimePicker Value="{Binding End, UpdateSourceTrigger=PropertyChanged}" Format="FullDateTime" ShowDropDownButton="False" HorizontalContentAlignment="Center"/>
<Button Content="Actualize" Command="{Binding ActualizeCommand}"/>
</StackPanel>
</Grid>
</Grid>
The first time these page is opened everything goes fine, page opens, lineseries are drawn and done.
When i update the itemsources of the lineseries, lineseries are drawn and ... applicationfreeze for a long time caused of heavy cpu usage. I linked an image of this.
green square = frist opening of the page, red square = update of itemsource (green bar = chart updated, all my code is done)
Following the update funtion:
public void Actualize()
{
WerteZentrale = null;
WerteZentraleCollection = null;
//Get values from db
WerteZentrale = new Vakuumverlauf_ZentraleEntities1();
WerteZentraleCollection = new ListCollectionView((from a in WerteZentrale.Werte_Zentrale0 where a.TimeString != string.Empty select a).ToList());
//filter
WerteZentraleCollection.Filter = (found) =>
{
Werte_Zentrale0 a = found as Werte_Zentrale0;
return (Convert.ToDateTime(a.TimeString) >= Start && Convert.ToDateTime(a.TimeString) <= Ende);
};
//sort
WerteZentraleCollection.CustomSort = new DateTimeComparerWerte();
//empty observablecollections
Istwerte1ListeDummy.Clear();
Sollwerte1ListeDummy.Clear();
Istwerte2ListeDummy.Clear();
Sollwerte2ListeDummy.Clear();
Istwerte1Liste.Clear();
Sollwerte1Liste.Clear();
Istwerte2Liste.Clear();
Sollwerte2Liste.Clear();
foreach (Werte_Zentrale0 Wert in WerteZentraleCollection)
{
//1
if (Wert.VarName == "VakuumWerte_VK1_Istwert_Istwert")
{
Istwerte1ListeDummy.Add(new KeyValuePair<DateTime, double?>(Convert.ToDateTime(Wert.TimeString), Wert.VarValue));
}
//1a
if (Wert.VarName == "VakuumWerte_VK1_Sollwert")
{
Sollwerte1ListeDummy.Add(new KeyValuePair<DateTime, double?>(Convert.ToDateTime(Wert.TimeString), Wert.VarValue));
}
//2
if (Wert.VarName == "VakuumWerte_VK2_Istwert_Istwert")
{
Istwerte2ListeDummy.Add(new KeyValuePair<DateTime, double?>(Convert.ToDateTime(Wert.TimeString), Wert.VarValue));
}
//2a
if (Wert.VarName == "VakuumWerte_VK2_Sollwert")
{
Sollwerte2ListeDummy.Add(new KeyValuePair<DateTime, double?>(Convert.ToDateTime(Wert.TimeString), Wert.VarValue));
}
}
//write to itemsource
Istwerte1Liste = Istwerte1ListeDummy;
Sollwerte1Liste = Sollwerte1ListeDummy;
Istwerte2Liste = Istwerte2ListeDummy;
Sollwerte2Liste = Sollwerte2ListeDummy;
}
This function is called in the constructor of the viewmodel, aswell as at the ActualizeCommand.
So for me, i'm doing the same thing in both cases but something different is the result and i have no clue why.
Related
I wrote a simple dialog (XAML/WPF) and a test app and the dialog looks fine. In particular the buttons in the ListView have rounded corners. I've posted a picture and the code below.
The problem? When I use this dialog inside a much larger program (codebase too large to share), the rounded corners and other styling is gone. I strongly suspect something in the larger program is taking precedence over my local work. Perhaps a global style for buttons or some such thing?
I'd like to understand what is going on. Presumably something in the main app takes precedence over my xaml work?
I'd like to know if there is a way to say "don't inherit styles from the app itself. Rather use WPF defaults unless I override them.", assuming that is the problem.
See picture (notice rounded corners)
See picture from when I call it from actual main application instead of test application
Notice in particular lack of rounded corners. My work to produce rounded corners is gone! Also, in the test app, hovering over a button shows a blue color which I assume is default (I didn't do it). When called from main app, no such hover effect. I suspect the main app gets rid of that somewhere.
Here's the simple dialog xaml
<Window x:Class="FirmsDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Dialogs"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="400"
Width="390" Height="720" BorderBrush="LightGray"
WindowStartupLocation="CenterScreen" ResizeMode="NoResize"
x:Name="FirmsViewDlg" Loaded="FirmsViewDlg_Loaded"
>
<Window.Resources>
<FontFamily x:Key="AvenirNextforCompany">
pack://application:,,,/Assets/Fonts/#AvenirNextforCompany
</FontFamily>
<local:ReverseObjectToBool x:Key="ReverseObjectToBoolConverter" />
<local:ObjectToBool x:Key="ObjectToBoolConverter" />
<!-- New style -->
<Style x:Key="StyleListViewItem" TargetType="ListViewItem">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Green"/>
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="Blue"/>
</Trigger>
</Style.Triggers>
</Style>
<!-- Existing style -->
<Style x:Key="StyleListView" TargetType="ListView">
<Setter Property="ItemContainerStyle" Value="{StaticResource StyleListViewItem}"/>
<Setter Property="SnapsToDevicePixels" Value="true"/>
<!-- ... -->
</Style>
</Window.Resources>
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Content="Select Company" HorizontalAlignment="Center" FontSize="20px" Foreground="#393a3d" FontFamily="{StaticResource AvenirNextforCompany}" FontWeight="Normal" ></Label>
<Label Grid.Row="1" Content="Accountant companies" Margin="10,0" FontFamily="{StaticResource AvenirNextforCompany}" FontSize="14px" Foreground="#8d9096" FontWeight="Normal"></Label>
<ListView BorderThickness="0" Grid.Row="2" ItemsSource="{Binding RealmMembershipInfo}" SelectedItem="{Binding SelectedFirm}" x:Name="realmListBox"
HorizontalContentAlignment="Stretch" HorizontalAlignment="Stretch" Height="Auto" Margin="0,0,0,0"
VerticalAlignment="Top" FontWeight="Bold" FontSize="14" Background="White"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
BorderBrush="LightGray">
<ListView.ItemTemplate>
<DataTemplate>
<Button Click="Button_Click"
MinHeight="65" Padding="10,0,10,0"
Margin="0,0,0,0" HorizontalContentAlignment="Left" HorizontalAlignment="Stretch" BorderBrush="LightGray" Background="White" Foreground="#393a3d" FontFamily="{StaticResource AvenirNextforCompany}" FontSize="14px" FontWeight="SemiBold"
>
<Button.Resources>
<Style TargetType="Border">
<Setter Property="CornerRadius" Value="9"/>
</Style>
</Button.Resources>
<TextBlock Text="{Binding displayName}" TextWrapping="Wrap" HorizontalAlignment="Stretch" Foreground="#393a3d" FontFamily="{StaticResource AvenirNextforCompany}" FontSize="14px" FontWeight="Bold" >
</TextBlock>
</Button>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Margin" Value="10,10,10,10"/>
<Setter Property="Padding" Value="0"/>
<Style.Triggers>
<Trigger Property="Control.IsMouseOver" Value="True">
<Setter Property="Control.Background" Value="Transparent" />
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="BorderThickness" Value="0" />
</Trigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
</ListView>
</Grid>
</Window>
Simple program to show the Xaml above
using Dialogs;
using Models;
using System.Collections.Generic;
using System.Windows;
namespace TestApp
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_SelectFirm(object sender, RoutedEventArgs e)
{
// hack code to set up dialog
RealmMembershipInfo realmInfo = new RealmMembershipInfo();
realmInfo.realmMembershipInfo = new List<RealmMembershipItem>();
RealmMembershipItem item = new RealmMembershipItem();
item.displayName = "Company 1";
realmInfo.realmMembershipInfo.Add(item);
item = new RealmMembershipItem();
item.displayName = "Company2";
realmInfo.realmMembershipInfo.Add(item);
FirmsDialog dlg = new FirmsDialog(realmInfo);
dlg.ShowDialog();
MessageBox.Show("Your picked firm: " + dlg.SelectedFirm);
}
private void Button_SelectClient(object sender, RoutedEventArgs e)
{
}
}
}
You haven't set the style on the Listview.
<ListView Style={StaticResource StyleListView} ....
And you are using the default style for the ItemsContainer. You need to add the a base style.
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem" BasedOn={StaticResource StyleListViewItem}...
i'm able to create dinamicaly both RadioButtions and CheckBoxes inside TreeViewItem using this code in Window1.cs initialization:
TreeViewItem parent = createTextInTree("Выпечка", tree);
createCheckBoxChildren("торт Птичье молоко - 350 звезд", parent);
createCheckBoxChildren("пироженное Тирамиссу - 25 UAH", parent);
createCheckBoxChildren("пироженное Тирамиссу - 70 звезд", parent);
createCheckBoxChildren("тарт Вишня - 35 звезд", parent);
parent = createTextInTree("Мороженное", tree);
createRadioButtonsChildren("ванильное - 15 звезд", parent, "grp1");
createRadioButtonsChildren("шоколадное - 15 звезд", parent, "grp1");
createRadioButtonsChildren("клубничное - 15 звезд", parent, "grp1");
parent = createTextInTree("Кофе", tree);
createRadioButtonsChildren("эспрессо - 30 звезд", parent, "grp2");
createRadioButtonsChildren("латте - 25 UAH", parent, "grp2");
createRadioButtonsChildren("латте - 50 звезд", parent, "grp2");
createRadioButtonsChildren("капучино - 35 звезд", parent, "grp2");
There methods are:
private TreeViewItem createTextInTree(string content, TreeView tree)
{
TreeViewItem item = new TreeViewItem()
{
Header = content
};
tree.Items.Add(item);
return item;
}
private TreeViewItem createCheckBoxInTree(string content, TreeView tree)
{
TreeViewItem item = new TreeViewItem()
{
Header = new CheckBox()
{
Content = content
}
};
tree.Items.Add(item);
return item;
}
private void createCheckBoxChildren(string content, TreeViewItem item)
{
TreeViewItem child = new TreeViewItem()
{
Header = new CheckBox()
{
Content = content,
}
};
item.Items.Add(child);
}
private void createRadioButtonsChildren(string content, TreeViewItem item, string group)
{
TreeViewItem childRadio = new TreeViewItem()
{
Header = new RadioButton()
{
Content = content,
GroupName = group,
}
};
item.Items.Add(childRadio);
}
Control now looks like that:
Control dialog
Using example: TreeView with Checkboxes I was succeded to use bindings in case i have only one model for TreeViewItem, but not in case i have multiple ones.
Here is my current xaml:
<Window.Resources>
<ResourceDictionary.MergedDictionaries>
</ResourceDictionary.MergedDictionaries>
<Style x:Key="TreeViewItemStyle" TargetType="TreeViewItem">
<Setter Property="IsExpanded" Value="True" />
<Setter Property="IsSelected" Value="{Binding IsInitiallySelected, Mode=OneTime}" >
<Setter Property="KeyboardNavigation.AcceptsReturn" Value="True" />
<Setter Property="dw:VirtualToggleButton.IsVirtualToggleButton" Value="True" />
<Setter Property="dw:VirtualToggleButton.IsChecked" Value="{Binding IsChecked}" />
<Setter Property="FontSize" Value="30"/>
</Style>
<Style TargetType="{x:Type TreeView}">
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="#CBE8F6" />
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Black" />
<SolidColorBrush x:Key="{x:Static SystemColors.ControlTextBrushKey}" Color="Black" />
</Style.Resources>
</Style>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="BorderThickness" Value="1" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="BorderBrush" Value="#26A0DA" />
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="True" />
<Condition Property="IsSelectionActive" Value="False" />
</MultiTrigger.Conditions>
<Setter Property="BorderBrush" Value="#DADADA" />
</MultiTrigger>
</Style.Triggers>
</Style>
<HierarchicalDataTemplate x:Key="RadioButtonItemTemplate" DataType="{x:Type local:FooViewModel2}" ItemsSource="{Binding Children, Mode=OneTime}">
<StackPanel Orientation="Horizontal">
<RadioButton Focusable="False" IsChecked="{Binding IsChecked}" VerticalAlignment="Center" />
<ContentPresenter Content="{Binding Name, Mode=OneTime}" Height="30" Margin="8,0" />
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate x:Key="CheckBoxItemTemplate" DataType="{x:Type local:FooViewModel}" ItemsSource="{Binding Children, Mode=OneTime}" >
<StackPanel Orientation="Horizontal">
<!-- These elements are bound to a FooViewModel object. -->
<CheckBox Focusable="False" IsChecked="{Binding IsChecked}" VerticalAlignment="Center" />
<ContentPresenter Content="{Binding Name, Mode=OneTime}" Height="30" Margin="8,0" />
</StackPanel>
</HierarchicalDataTemplate>
</ResourceDictionary>
</Window.Resources>
<Window.DataContext>
</Window.DataContext>
<DockPanel>
<TreeView x:Name="tree" Width="450" ItemContainerStyle="{StaticResource TreeViewItemStyle}" ItemsSource="{Binding Mode=OneTime}" ItemTemplate="{StaticResource RadioButtonItemTemplate}" />
<StackPanel Background="White">
<Button Command="Undo" Content="Uncheck All" HorizontalAlignment="Stretch" Margin="0,2" Padding="8,0"/>
<Button DockPanel.Dock="Bottom" Content="Ok" HorizontalAlignment="Stretch" Margin="0,2" Padding="8,0"/>
<Button DockPanel.Dock="Bottom" IsCancel="True" IsDefault="True" Content="Отмена" HorizontalAlignment="Stretch" Margin="0,2" Padding="8,0"/>
<Label Name="lblTotalBonusesTitle" Content="Всего бонусов" HorizontalAlignment="Center" FontWeight="Bold" Margin="0,2" Padding="1,0" />
<Label Name="lblTotalBonuses" Content="750" HorizontalAlignment="Center" Margin="0,2" Padding="1,0" />
<Label Name="lblChosenBonusesTitle" Content="Выбрано" HorizontalAlignment="Center" FontWeight="Bold" Margin="0,2" Padding="1,0" />
<Label Name="lblChosenBonuses" Content="320" HorizontalAlignment="Center" FontWeight="DemiBold" Margin="0,2" Padding="1,0" />
<Label Name="lblChosenStrTitle" Content="Выбраны" HorizontalAlignment="Center" FontWeight="Bold" Margin="0,2" Padding="1,0" />
<Label Name="lblChosenStr" Content="" HorizontalAlignment="Center" FontWeight="DemiBold" Margin="0,2" Padding="1,0" />
</StackPanel>
</DockPanel>
I settled on using a DataTemplateSelector. This is a custom class with a method that returns a DataTemplate based on whatever criteria you need. The custom DataTemplateSelector is then assigned to the element: in the case of ListBox it is the ItemTemplateSelector property.
My customer developing a property editor of sorts that contains multiple property sections that are presented as WPF Expanders with Datagrids contained within. We have everything laid out in a WPF Grid, currently with auto sized rows.
The problem we're trying to solve is proportional sizing of each property section when the screen height changes. When expanders are opened they should take up a proportional amount of space with vertical scrollbars kicking automatically when needed. When they are closed they should collapse and give the remaining space to the remaining sections.
In real life we have 4 expanders with content. The first one is a fixed height, the remaining three are Lists and DataGrids that need to size proportionally with the last one getting the largest portion of the remaining space. Keep in mind, users might resize the screen, or users might be running in different screen resolutions, so we need it to react accordingly.
We've tried messing with the DataGrid RowDefinition Height (fixed, proportional and auto) and MaxHeight, and also the MaxHeight of each datagrid, but I can't seem to find a combination that causes the whole area to be consumed when needed. We're researching a code based solution, but we're curious what others may suggest.
Here's a simple code sample that will give you the layout we're after. We just need it to work as described above.
Here's The Code (this would be a view model in real world)
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
datagrid1.DataContext = GetCustomerVM();
datagrid2.DataContext = GetCustomerVM();
datagrid3.DataContext = GetCustomerVM();
}
private List<Customer> GetCustomerVM()
{
var CustomerList = new List<Customer>();
CustomerList.Add(new Customer() { FirstName = "A" });
CustomerList.Add(new Customer() { FirstName = "A" });
CustomerList.Add(new Customer() { FirstName = "A" });
CustomerList.Add(new Customer() { FirstName = "A" });
CustomerList.Add(new Customer() { FirstName = "A" });
CustomerList.Add(new Customer() { FirstName = "A" });
CustomerList.Add(new Customer() { FirstName = "A" });
CustomerList.Add(new Customer() { FirstName = "A" });
return CustomerList;
}
}
public class Customer
{
public string FirstName { get; set; }
}
The XAML
<Window x:Class="StackOverflow_SidePanelGridScrolling.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:StackOverflow_SidePanelGridScrolling"
mc:Ignorable="d"
Loaded="Window_Loaded"
Title="MainWindow" Height="500" Width="300">
<Window.Resources>
<DataTemplate x:Key="ExpanderHeaderTemplate">
<DockPanel Height="30">
<TextBlock Margin="4,0,0,0"
VerticalAlignment="Center"
DockPanel.Dock="Left"
FontSize="16"
Text="{Binding}" />
</DockPanel>
</DataTemplate>
<Style TargetType="Expander">
<Setter Property="HeaderTemplate"
Value="{StaticResource ExpanderHeaderTemplate}" />
</Style>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Expander x:Name="expander1" Grid.Row="0" Header="Area 1">
<DataGrid Name="datagrid1"
ItemsSource="{Binding}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="First Name"
Binding="{Binding FirstName}"
Width="100*" />
</DataGrid.Columns>
</DataGrid>
</Expander>
<Expander x:Name="expander2" Grid.Row="1" Header="Area 2">
<DataGrid Name="datagrid2"
ItemsSource="{Binding}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="First Name"
Binding="{Binding FirstName}"
Width="100*" />
</DataGrid.Columns>
</DataGrid>
</Expander>
<Expander x:Name="expander3" Grid.Row="3" Header="Area 3">
<DataGrid Name="datagrid2"
ItemsSource="{Binding}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="First Name"
Binding="{Binding FirstName}"
Width="100*" />
</DataGrid.Columns>
</DataGrid>
</Expander>
</Grid>
</Window>
As far as I'm able to understand your requirements, I think this does about what you want:
Every expander, when not expanded, takes up whatever minimal space it requires.
The top row, when expanded, is sized to its content.
Rows two, three, and four divide up the remainder of the space. When expanded, they stretch. Two gets one share of the available space, Three gets two shares, Four gets three shares. If Two and Three are open, Two gets one of four shares and Three gets the other three.
Those shares are handed out by the * Height values in the setters in the triggers. Here's the trigger for Row Four:
<DataTrigger
Binding="{Binding Children[3].IsExpanded, RelativeSource={RelativeSource AncestorType=Grid}}"
Value="True"
>
<Setter Property="Height" Value="3*" />
</DataTrigger>
The nice thing about doing this in XAML is that it will never spring any ugly surprises on you.
So here's the XAML:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition>
<RowDefinition.Style>
<Style TargetType="RowDefinition">
<Setter Property="Height" Value="Auto" />
<Style.Triggers>
<DataTrigger
Binding="{Binding Children[1].IsExpanded, RelativeSource={RelativeSource AncestorType=Grid}}"
Value="True"
>
<Setter Property="Height" Value="1*" />
</DataTrigger>
</Style.Triggers>
</Style>
</RowDefinition.Style>
</RowDefinition>
<RowDefinition>
<RowDefinition.Style>
<Style TargetType="RowDefinition">
<Setter Property="Height" Value="Auto" />
<Style.Triggers>
<DataTrigger
Binding="{Binding Children[2].IsExpanded, RelativeSource={RelativeSource AncestorType=Grid}}"
Value="True"
>
<Setter Property="Height" Value="2*" />
</DataTrigger>
</Style.Triggers>
</Style>
</RowDefinition.Style>
</RowDefinition>
<RowDefinition>
<RowDefinition.Style>
<Style TargetType="RowDefinition">
<Setter Property="Height" Value="Auto" />
<Style.Triggers>
<DataTrigger
Binding="{Binding Children[3].IsExpanded, RelativeSource={RelativeSource AncestorType=Grid}}"
Value="True"
>
<Setter Property="Height" Value="3*" />
</DataTrigger>
</Style.Triggers>
</Style>
</RowDefinition.Style>
</RowDefinition>
</Grid.RowDefinitions>
<Expander
Grid.Row="0"
VerticalAlignment="Stretch"
Header="One" Background="LightGreen">
<StackPanel>
<Label>Content One</Label>
<Label>Content One</Label>
<Label>Content One</Label>
</StackPanel>
</Expander>
<Expander
Grid.Row="1"
VerticalAlignment="Stretch"
Header="Two" Background="LightSkyBlue">
<StackPanel>
<Label>Content Two</Label>
<Label>Content Two</Label>
<Label>Content Two</Label>
</StackPanel>
</Expander>
<Expander
Grid.Row="2"
VerticalAlignment="Stretch"
Header="Three" Background="LightGoldenrodYellow">
<StackPanel>
<Label>Content Three</Label>
<Label>Content Three</Label>
<Label>Content Three</Label>
</StackPanel>
</Expander>
<Expander
Grid.Row="3"
VerticalAlignment="Stretch"
Header="Four" Background="Khaki">
<StackPanel>
<Label>Content Four</Label>
<Label>Content Four</Label>
<Label>Content Four</Label>
</StackPanel>
</Expander>
</Grid>
These don't show scrollbars because I didn't take the time to create content that will scroll.
Tererik's documentation is deplorable (or I can't find it). Anyway, anyone have a tip on styling the tick marks for a RadSlider?
I've managed to find this much, that I need to create a RadBarStyle but setting the Foreground doesn't change the ticks, setting the Background does change the bar's background, but has no effect on the ticks.
My code:
<StackPanel Grid.Column="1">
<StackPanel.Resources>
<Style x:Key="ticks" TargetType="{x:Type telerik:RadTickBar}">
<Setter Property="Foreground" Value="White" />
</Style>
</StackPanel.Resources>
<TextBlock Text="Brightness" Margin="5 5 0 10" />
<telerik:RadSlider ValueChanged="RadSlider_ValueChanged"
Ticks="0"
TickPlacement="Both"
Minimum="-100" Maximum="200" LargeChange="10"
SmallChange="5"
TickBarStyle="{StaticResource ticks}"
/>
</StackPanel>
The Tick is a rectangle, if you just want to change it's color you can use something like this:
<StackPanel Grid.Column="1">
<StackPanel.Resources>
<Style x:Key="ticks" TargetType="{x:Type telerik:RadTickBar}">
<Setter Property="Foreground" Value="White" />
</Style>
</StackPanel.Resources>
<TextBlock Margin="5 5 0 10" Text="Brightness" />
<telerik:RadSlider LargeChange="10"
Maximum="200"
Minimum="-100"
SmallChange="5"
TickBarStyle="{StaticResource ticks}"
TickPlacement="Both"
Ticks="0"
ValueChanged="RadSlider_ValueChanged">
<telerik:RadSlider.TickTemplate>
<DataTemplate>
<Rectangle Width="1"
Height="5"
Fill="Red" />
</DataTemplate>
</telerik:RadSlider.TickTemplate>
</telerik:RadSlider>
</StackPanel>
Is there a way to create a visual separator between two particular columns in a DataGrid? It doesn't need to be fancy, maybe just a double line or a thicker border.
In case it's something like this
You can achieve using a custom style:
<Window.Resources>
<Style x:Key="DataGridColumnSeparatorStyle" TargetType="DataGridCell">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Rectangle VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Fill="Gray"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<DataGrid x:Name="dataGrid" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Start"/>
<DataGridTextColumn Header="End"/>
<!-- Separator column -->
<DataGridTemplateColumn MinWidth="0" Width="2" CellStyle="{StaticResource DataGridColumnSeparatorStyle}"/>
<DataGridTextColumn Header="Start"/>
<DataGridTextColumn Header="End"/>
</DataGrid.Columns>
</DataGrid>
If you generate the columns in code-behind, either by autogenerate columns or other, you can still create the separator column by getting the resource from the XAML:
DataGridTextColumn s1 = new DataGridTextColumn() { Header = "Start" };
DataGridTextColumn s2 = new DataGridTextColumn() { Header = "Start" };
DataGridTextColumn e1 = new DataGridTextColumn() { Header = "End" };
DataGridTextColumn e2 = new DataGridTextColumn() { Header = "End" };
DataGridTemplateColumn column = new DataGridTemplateColumn();
column.MinWidth = 0;
column.Width = 2;
var separatorStyle = (Style)FindResource("DataGridColumnSeparatorStyle");
column.CellStyle = separatorStyle;
dataGrid.Columns.Add(s1);
dataGrid.Columns.Add(e1);
dataGrid.Columns.Add(column);
dataGrid.Columns.Add(s2);
dataGrid.Columns.Add(e2);
I think you have two options. The simplest option will probably be to use a Style and set your DataGrid.CellStyle to the defined style.
<Style x:Key="DataGridBorder" TargetType="DataGridCell">
<Setter Property="BorderBrush" Value="LightGray" />
<Setter Property="BorderThickness" Value="1,1,1,1" />
</Style>
...
<DataGrid CellStyle="{StaticResource DataGridBorder}">
...
The other option is to use a CellTemplate in conjunction with the DataGridTemplateColumn.
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Border BorderBrush="LightGray" BorderThickness="1,1,1,1" Margin="-6,-6,-6,-6">
<Grid Margin="6,6,6,6">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Whatever}" Grid.Column="0" TextTrimming="CharacterEllipsis" VerticalAlignment="Center" />
</Grid>
</Border>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
I haven't tested either of these, and you may have to play with the margins a little bit.
Try this. When navigating through cells using keyboard Tab key, it won't focus the seperator column:
<DataGridTemplateColumn MinWidth="2" MaxWidth="2" IsReadOnly="True" CanUserResize="False">
<DataGridTemplateColumn.HeaderStyle>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="Background" Value="Gray" />
<Setter Property="BorderBrush" Value="Gray" />
<Setter Property="BorderThickness" Value="2" />
</Style>
</DataGridTemplateColumn.HeaderStyle>
<DataGridTemplateColumn.CellStyle>
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="BorderBrush" Value="Gray" />
<Setter Property="BorderThickness" Value="2" />
<Setter Property="Focusable" Value="False" />
</Style>
</DataGridTemplateColumn.CellStyle>
</DataGridTemplateColumn>
Source