wpf TreeView binding having multiple TreeViewItemStyle - wpf

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.

Related

WPF chart heavy cpu usage on update itemsource

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.

how to bind collection to custom control in wpf

I am building a custom control and I want to pass a collection to it so that control display that collection, my code is as the following :
<gm:Calendar SubscriptionSource="{Binding Subscriptions}"></gm:Calendar>
and in Custom control "Calendar"
public static readonly DependencyProperty SubscriptionSourceProperty =
DependencyProperty.Register(
"SubscriptionSource",
typeof(ObservableCollection<Subscription>),
typeof(Calendar),
new FrameworkPropertyMetadata(new ObservableCollection<Subscription>()));
public ObservableCollection<Subscription> SubscriptionSource
{
get
{
return (ObservableCollection<Subscription>)GetValue(SubscriptionSourceProperty);
}
set
{
SetValue(SubscriptionSourceProperty, value);
}
}
I use in generic.xaml
<ItemsControl ItemsSource="{Binding SubscriptionSource}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<!--Box-->
<Border BorderBrush="Black" BorderThickness="1" Padding="0">
<Border Name="InnerBorder" BorderBrush="{Binding Path=Day, Converter={StaticResource DayBorderColorConverter}}" BorderThickness="2">
<Border.Style>
<Style TargetType="{x:Type Border}">
<Style.Triggers>
<!--Current Day-->
<DataTrigger Binding="{Binding IsToday}" Value="true">
<Setter Property="Border.Background">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF1EA6C8" Offset="0"/>
<GradientStop Color="#FF0691B3" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<DockPanel>
<!--Day Number-->
<StackPanel Orientation="Horizontal" DockPanel.Dock="Top" FlowDirection="RightToLeft">
<TextBlock TextAlignment="Right" Text="{Binding Day.Date, Converter={StaticResource DateConverter}, ConverterParameter=DAY}" FontSize="12" Margin="5,5,5,5" >
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsTargetMonth}" Value="false">
<Setter Property="TextBlock.Foreground" Value="Gray"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</StackPanel>
<CheckBox IsEnabled="{Binding IsEnabled}" Style="{StaticResource DiscreteCheckBoxStyle}" />
</DockPanel>
</Border>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Rows="6" Columns="7" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
I want to Bind Subscriptions observable collection to the calendar custom control so I can use the collection in the custom control, is there is away to do this?
If the ItemsControl is inside the ControlTemplate, then Change the {Binding SubscriptionSource} for {TemplateBinding SubscriptionSource}
My problem is now Solved thanks to #Luke Woodward and I just had another problem that I use the custom control inside usercontrol and that usercontrol was an item inside ListItem
I modified the binding expression
<gm:Calendar SubscriptionSource="{Binding Path=Subscriptions,Mode=TwoWay}" >
and the customcontrol is
static Calendar()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(Calendar), new FrameworkPropertyMetadata(typeof(Calendar)));
}
public ObservableCollection<SubscriptionDay> SubscriptionSource
{
get { return (ObservableCollection<SubscriptionDay>)GetValue(SubscriptionSourceProperty); }
set { SetValue(SubscriptionSourceProperty, value); }
}
public static readonly DependencyProperty SubscriptionSourceProperty =
DependencyProperty.Register("SubscriptionSource", typeof(ObservableCollection<SubscriptionDay>), typeof(Calendar), new FrameworkPropertyMetadata(new ObservableCollection<SubscriptionDay>()));
and in the Generic.xaml modified as #HighCore posted
<ItemsControl ItemsSource="{TemplateBinding SubscriptionSource}">
<ItemsControl.ItemTemplate>
<DataTemplate>......
and finally worked.
Thanks to #Luke Woodward and #HighCore

Set a Usercontrol as a Datatemplate

I have the following ProductList template snipet
<Style x:Key="ProductListStyle" TargetType="{x:Type s:SurfaceListBox }">
<Setter Property="Background" Value="{DynamicResource {x:Static s:SurfaceColors.ListBoxItemBackgroundBrushKey}}" />
<Setter Property="SelectionMode" Value="Single" />
<Setter Property="Height" Value="234" />
<Setter Property="ItemTemplateSelector">
<Setter.Value>
<sc:ProductListTemplateSelector>
<sc:ProductListTemplateSelector.NormalItemTemplate>
<DataTemplate>
<StackPanel RenderTransformOrigin="0.5, 0.5"
Margin="7,0,0,0"
MinWidth="171" MaxWidth="171"
MinHeight="235" MaxHeight="235">
<Image Margin="14,21,21,11" Source="{Binding XPath=#Image}"
Height="149" Width="101" />
<TextBlock Text="{Binding XPath=#Name}"
MaxWidth="116"
FontSize="12"
Margin="21,0,21,21"
FontFamily="Segoe360"
TextAlignment="Center"
TextWrapping="Wrap"
Foreground="{DynamicResource {x:Static s:SurfaceColors.ListBoxItemForegroundBrushKey}}"
HorizontalAlignment="Center" />
</StackPanel>
</DataTemplate>
</sc:ProductListTemplateSelector.NormalItemTemplate>
I need to replace the DataTemplate of this style to be set using my user control like
<local:MyUserControl>
By keeping only between section I did not get my control displayed when my Itemsource is set with a collection of myUserControl
Usually I just add the DataTemplate in the Resources. This can be <Window.Resources> or <App.Resources> if the data template is global, or FrameworkElement.Resources if the template should only be applied in a specified scope. For example, adding the template to ListView.Resources would only apply the template within a specific ListView.
<Window.Resources>
<DataTemplate DataType="{x:Type local:ProductModel}">
<local:MyUserControl />
</DataTemplate>
</Window.Resources>
As a side note, your original question leads me to believe that you are binding a ListView to a collection of MyUserControl objects. I really wouldn't recommend this, but if this is the case you can use a ContentControl in your DataTemplate with it's Content bound to your object, and it should display correctly.
<ContentControl Content="{Binding }" />

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).

Dynamically change the content of of control based on a value

I want to achieve the following behavior:
Depending on a value use a different datatemplate:
<DataTemplate x:Key="cardTemplate2">
<Border x:Name="container">
.....
</Border>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding ShowSecondDT}" Value="True">
<Setter Property="Child" TargetName="container">
<Setter.Value>
<StackPanel Orientation="Vertical" >
</StackPanel>
</Setter.Value>
</Setter>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
The application fails claiming that Setter Property="Child" is null...
Another information is that this Datatemplate in the resource of a control: (devexpress gris)
<dxg:GridControl xmlns:dxg="http://schemas.devexpress.com/winfx/2008/xaml/grid"
x:Name="gridTitulaire" DataSource="{Binding Contacts}" Width="600" >
<dxg:GridControl.Resources>
<DataTemplate x:Key="cardTemplate2">
<Border x:Name="container">
<StackPanel Orientation="Horizontal" >
</StackPanel>
</Border>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding isTitulairePrincipal}" Value="True">
<Setter Property="Child" TargetName="container">
<Setter.Value>
<StackPanel Orientation="Vertical" >
</StackPanel>
</Setter.Value>
</Setter>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</dxg:GridControl.Resources>
<dxg:GridControl.Columns>
<dxg:GridColumn FieldName="first_name"/>
<dxg:GridColumn FieldName="last_name"/>
</dxg:GridControl.Columns>
<dxg:GridControl.View>
<dxg:CardView x:Name="view" ShowGroupedColumns="True" CardTemplate="{DynamicResource cardTemplate2}" />
</dxg:GridControl.View>
</dxg:GridControl>
Any idea ?
Thanks
Jonathan
Define two separate data templates (call them CardTemplateV for the vertical one, and CardTemplateH for the horizontal one, for example), and set the CardTemplateSelector to a selector object that checks the discriminating field.
Example:
class MyTemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
var cardData = item as CardData;
if (cardData == null) return null;
var dataObject = cardData.DataContext as YourDataType;
if (dataObject == null) return null;
if (dataObject.isTitulairePrincipal)
return (DataTemplate)App.Current.FindResource("CardTemplateV");
else
return (DataTemplate)App.Current.FindResource("CardTemplateH");
}
}
In the XAML add the selector to the resource dictionary and reference it from the grid:
<Window.Resources>
<local:YourTemplateSelector x:Key="MyTemplateSelector"/>
</Window.Resources>
...
<dxg:CardView
x:Name="view"
ShowGroupedColumns="True"
CardTemplateSelector="{StaticResource MyTemplateSelector}"/>
...

Resources