accessing control item when given inner template element - c#

I have a TreeviewItem with a style set to this
<Style x:Key="TreeViewItemStyle" TargetType="TreeViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TreeViewItem">
<StackPanel x:Name="stackpanel" Orientation="Horizontal">
<CheckBox x:Name="checkbox_treeview" Checked="treeView_AfterCheck" Unchecked="treeView_AfterCheck"/>
<Image x:Name="image_treeview" Width="16"/>
<local:WPFEditableTextBlock x:Name="label_TreeView" Text="{TemplateBinding Header}"/>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I am able to access the checkbox of the template by doing this
TreeViewItem folderNode = new TreeViewItem();
Style style = this.FindResource("TreeViewItemStyle") as Style;
folderNode.Style = style;
ControlTemplate controlTemplate = folderNode.Template;
var templatedControl = folderNode.Template.LoadContent() as FrameworkElement;
CheckBox chbx = (CheckBox)templatedControl.FindName("checkbox_treeview");
once I am able to access this checkbox I have it go to the checked event handler. within that I want to be able to access the treeViewItem that contains that checkbox, but I can't figure out how to do this. Please help me out!!!

To access the treeViewItem from the checkbox defined in the template you could pass it in the Tag property from xaml like so:
<ControlTemplate TargetType="TreeViewItem">
<StackPanel x:Name="stackpanel" Orientation="Horizontal">
<CheckBox x:Name="checkbox_treeview" Tag="{Binding RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}}}" Checked="treeView_AfterCheck" Unchecked="treeView_AfterCheck"/>
<Image x:Name="image_treeview" Width="16"/>
<local:WPFEditableTextBlock x:Name="label_TreeView" Text="{TemplateBinding Header}"/>
</StackPanel>
</ControlTemplate>
and here how to retrieve it from the event handler:
private void treeView_AfterCheck(object sender, RoutedEventArgs e)
{
var tvi = ((sender as CheckBox).Tag as TreeViewItem);
}

Related

Binding a command to a checkbox for onclick inside a xamdatagrid in wpf not working

I have a checkbox inside my XamDataGrid , as follows :-
<igDp:UnboundField Width="1*" Label="{LocText props:Resources.GROUPLIST_SYNC}" BindingMode="TwoWay" BindingPath="IsSynchronise.Value" Converter="{StaticResource BoolToUMDirectoryFilter}" ConverterParameter="Enabled" ToolTip="{LocText props:Resources.GROUPLIST_SYNC}">
<igDp:UnboundField.Settings>
<igDp:FieldSettings AllowEdit="True">
<igDp:FieldSettings.LabelPresenterStyle >
<Style TargetType="igDp:LabelPresenter" BasedOn="{StaticResource GmsLabelStyle }">
<Setter Property="AutomationProperties.AutomationId" Value="Group_SYNC"></Setter>
</Style>
</igDp:FieldSettings.LabelPresenterStyle>
<igDp:FieldSettings.CellValuePresenterStyle>
<Style TargetType="{x:Type igDp:CellValuePresenter}">
<Setter Property="Margin" Value="2"></Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="igDp:CellValuePresenter">
<CheckBox Name="chkSynchronise" IsChecked="{Binding Path=DataContext.DataItem.IsSynchronise.Value, RelativeSource={ RelativeSource Mode=TemplatedParent}}"
HorizontalAlignment="Center" Command="{Binding SynchroniseGroups,RelativeSource={RelativeSource Mode=Self}}" HorizontalContentAlignment="Left" >
</CheckBox>
<!--<CheckBox IsChecked="{Binding Path=DataContext.DataItem.IsSynchronise.Value, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged, RelativeSource={ RelativeSource Mode=TemplatedParent}}"
Command="{Binding SynchroniseGroups,RelativeSource={RelativeSource Mode=Self}}"
HorizontalAlignment="Center" HorizontalContentAlignment="Left" >
</CheckBox>-->
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</igDp:FieldSettings.CellValuePresenterStyle>
</igDp:FieldSettings>
</igDp:UnboundField.Settings>
</igDp:UnboundField>
So, how should I bind a command to checkbox in order to work it with click and get the behaviour of checked and unchecked inside my ViewModel? Any help would be much appreciated. Thanks in advance.
At first I want to add a side note: Since infragistics release 14.2 the unbound field is obsolete (look here).
For binding a boolean to the XamDataGrid I prefer using a CheckBoxField.
Class:
public class YourClass : NotificationObject
{
private bool _checkBoxValue;
public bool CheckboxValue
{
get
{
return this._checkBoxValue;
}
set
{
if (this._checkBoxValue != value)
{
this._checkBoxValue = value;
// Do something: Event, Method, ...
this.RaisePropertyChanged(nameof(this.CheckboxValue));
}
}
}
}
XAML:
<igDp:FieldLayout>
<igDp:CheckBoxField BindingType="UseAlternateBinding"
Name="CheckerField"
Label="YourCheckerFieldLabel"
ToolTip="YourTooltip"
AlternateBinding="{Binding CheckboxValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
/>
</igDp:FieldLayout>

check PasswordBox Value WPF

I have a password box, but i also have a textblock as hint text within the control template. I'd like this to be removed when the password box has a value. I have tried this below but it doesn't work, how can I do this?
Simplified XAML :
<PasswordBox Height="20" Name="pwdBox" PasswordChanged="pwdBox_PasswordChanged" Style="{DynamicResource PasswordBoxStyle1}"/>
<Style x:Key="PasswordBoxStyle1" TargetType="{x:Type PasswordBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type PasswordBox}">
<Border x:Name="Border" .. >
<StackPanel ..>
<TextBlock x:Name="LabelTextBlock" ...
Text="Password Label" />
<Grid>
<ScrollViewer x:Name="PART_ContentHost"
Focusable="false"
HorizontalScrollBarVisibility="Hidden"
VerticalScrollBarVisibility="Hidden"/>
<TextBlock x:Name="HintTextBlock"
Focusable="False"
IsHitTestVisible="False"
Opacity="0"
Text="Enter Your Password" />
</Grid>
</StackPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Code Behind :
private void pwdBox_PasswordChanged(object sender, RoutedEventArgs e)
{
if (pwdBox.SecurePassword.Length == 0)
{
HintTextBlock.IsVisible = true;
}
else
{
HintTextBlock.IsVisible = false;
}
}
It says that the name 'HintTextBlock does not exist in the current context'
Since, the text box HintTextBlock is part of Template of PassworkBox so it can not accessed directly as it is not part of direct control of window. Use the FindName to find the control in template of passwordbox.
TextBlock hintTextBlock = pwdBox.Template.FindName("HintTextBlock", pwdBox) as TextBlock;
if (pwdBox.SecurePassword.Length == 0)
{
hintTextBlock.Visiblility = Visiblitity.Visible;
}
else
{
hintTextBlock.Visiblility = Visiblility.Collapsed;
}

Using in code-behind a custom `Style`, declared in xaml, throws run-time error

I declare a style in xaml that I need to use and apply to a user control in code behind and when I use the same style twice the following error throws:
Element already has a logical parent. It must be detached from the old
parent before it is attached to a new one.
What am I doing wrong? I need to create multiple controls of the same user-control-type in code behind and apply one and the same Style to it.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:dxdo="http://schemas.devexpress.com/winfx/2008/xaml/docking"
xmlns:s="http://schemas.abtsoftware.co.uk/scichart"
x:Class="MyChartControl.MainWindow"
Title="MainWindow" Height="655" Width="1020">
<Window.Resources>
<Style x:Key="SciChartSurfaceStyle" TargetType="{x:Type s:SciChartSurface}">
<Setter Property="XAxis">
<Setter.Value>
<s:DateTimeAxis Visibility="Visible"
TextFormatting="dd/MM/yyyy"
SubDayTextFormatting="dd/MM/yyyy HH:mm:ss.fff"
GrowBy="0.02, 0.02"/>
</Setter.Value>
</Setter>
<Setter Property="YAxis">
<Setter.Value>
<s:NumericAxis AxisAlignment="Right"
Visibility="Visible"
TextFormatting="{Binding YAxisFormatting}"
GrowBy="0.02, 0.02"
AutoRange="Always"/>
</Setter.Value>
</Setter>
<Setter Property="ChartModifier">
<Setter.Value>
<s:ModifierGroup>
<s:RubberBandXyZoomModifier IsAnimated = "False" IsXAxisOnly = "True" ExecuteOn = "MouseRightButton"/>
<s:ZoomPanModifier XyDirection="XYDirection" ClipModeX = "ClipAtExtents" ExecuteOn ="MouseLeftButton" />
<s:MouseWheelZoomModifier XyDirection = "XYDirection"/>
<s:ZoomExtentsModifier IsAnimated = "False" ExecuteOn = "MouseDoubleClick" />
<s:XAxisDragModifier DragMode = "Scale"/>
<s:CursorModifier SourceMode="AllSeries" UseInterpolation="True"/>
<s:LegendModifier ShowLegend="True" LegendPlacement ="Inside" GetLegendDataFor="AllSeries" Margin="10"/>
<!--<s:SeriesSelectionModifier ReceiveHandledEvents="True">
<s:SeriesSelectionModifier.SelectedSeriesStyle>
<Style TargetType="s:BaseRenderableSeries">
<Setter Property="SeriesColor" Value="White"/>
<Setter Property="PointMarkerTemplate">
<Setter.Value>
<ControlTemplate>
<s:EllipsePointMarker Fill="#FF00DC" Stroke="White" Width="7" Height="7"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</s:SeriesSelectionModifier.SelectedSeriesStyle>
</s:SeriesSelectionModifier>-->
</s:ModifierGroup>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="32" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Horizontal" Background="Black">
<TextBlock Text="Dataseries Type:" Margin="5,0" VerticalAlignment="Center" FontSize="12" Foreground="White"/>
<ComboBox x:Name="ComboBox_ChooseSeriesType" MinWidth="140" Margin="5,3" VerticalContentAlignment="Center"/>
<TextBlock Text="Theme:" Margin="5,0" VerticalAlignment="Center" FontSize="12" Foreground="White"/>
<ComboBox x:Name="ComboBox_ChooseTheme" MinWidth="140" Margin="5,3" VerticalContentAlignment="Center"/>
</StackPanel>
<dxdo:LayoutGroup Grid.Row="1" x:Name="LayoutGroup" Orientation="Vertical">
<!--<dxdo:LayoutPanel Name="Panel1">
<s:SciChartSurface Name="Surface1" Style="{StaticResource SciChartSurfaceStyle}"></s:SciChartSurface>
</dxdo:LayoutPanel>-->
</dxdo:LayoutGroup>
</Grid>
And the code-behind method that retrieves the style and applies it:
private void TestSomeStuff()
{
var style = this.TryFindResource("SciChartSurfaceStyle") as Style;
var sciChartSurface1 = new SciChartSurface() {Style = style};
var panel1 = new LayoutPanel(){Content=sciChartSurface1};
var style2 = this.TryFindResource("SciChartSurfaceStyle") as Style;
var sciChartSurface2 = new SciChartSurface() {Style = style2};
var panel2 = new LayoutPanel() {Content = sciChartSurface2};
LayoutGroup.Add(panel1);
LayoutGroup.Add(panel2);
}
EDIT
Adding panel1 to LayoutGroup works just fine but the run-time error occurs as soon as I attempt to add panel2. Also, as long as do not inject style into a new instance of SciChartSurface it works just fine. The error pops up as soon as I inject the style into both new surfaces.
Do not set Style in code behind directly:
var style = this.TryFindResource("SciChartSurfaceStyle") as Style;
var sciChartSurface1 = new SciChartSurface() {Style = style};
but with SetValue method:
var style = this.TryFindResource("SciChartSurfaceStyle") as Style;
var sciChartSurface1 = new SciChartSurface();
sciChartSurface1.SetValue(StyleProperty, style);

Get Value from a Label in a Template for a Listboxitem

My problem is that I need the Value of a Label in a Template as a string. Its a Template for a ListBoxItem with a CheckBox and a Label. When the box get checked I need the Value of the Label as a string variable in the code.
ListBox
<ListBox HorizontalAlignment="Left" Height="196" Margin="10,24,0,0"
VerticalAlignment="Top" Width="155" BorderBrush="#FF7799BB"
Name="ListBoxTblColumns" DataContextChanged="TableColumns_DataContextChanged"
ItemsSource="{Binding Columns}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox Name="columnSelectBox" Margin="0,7,4,0" Checked="columnSelectBox_Checked" Unchecked="columnSelectBox_Unchecked"/>
<Label Name="lblColName" Content="{Binding}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Focusable" Value="False"/>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
And in this event I want to get the value from lblColName:
public void columnSelectBox_Checked(object sender, RoutedEventArgs e)
{
string colName = ...;
}
Ideas?

Get TreeViewItem's parent in HierarchicalDataTemplate in WPF

I am merging two examples found on the internet. One about stretched selection styles and one about multi-selection in a treeview.
I have everything working, except for the indentations of the treeview. I could give all my code, but that wouldn't solve it.
My problem lies in the following method:
public static class TreeViewItemExtensions
{
public static int GetDepth(this TreeViewItem item)
{
FrameworkElement elem = item;
while (elem.Parent != null)
{
var tvi = elem.Parent as TreeViewItem;
if (tvi != null)
return tvi.GetDepth() + 1;
elem = elem.Parent as FrameworkElement;
}
return 0;
}
}
This method tries to retrieve the depth of a treeviewItem in the tree. The problem is: elem.Parent is always null. Which results in depths of 0.
I think this is happening, because I am using an HierarchicalDataTemplate. A part of my xaml looks like this.
<TreeView Name="folderTree"
ItemsSource="{Binding Folders}"
SelectedItemChanged="folderTree_SelectedItemChanged"
HorizontalContentAlignment="Stretch">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Folders}"
DataType="{x:Type Model:IFolder}">
<StackPanel Orientation="Horizontal">
<StackPanel.Style>
<Style TargetType="{x:Type StackPanel}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsSelected}"
Value="True">
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
<Image Source="{Binding Converter={StaticResource iconConverter}}" Height="{Binding ElementName=theFile,Path=ActualHeight}"/>
<TextBlock Text="{Binding FileName}" Name="theFile"/>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
The XAML for my style of the treeview looks like this:
<Style x:Key="{x:Type TreeViewItem}" TargetType="{x:Type TreeViewItem}">
<!-- leaving some stuff out here -->
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TreeViewItem}">
<ControlTemplate.Resources>
<local:LeftMarginMultiplierConverter Length="19" x:Key="lengthConverter" />
</ControlTemplate.Resources>
<StackPanel>
<!-- The upper part of the TreeViewItem -->
<Border Name="Bd"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}">
<!-- The margin is what we try to measure, how can we get the parents from the templatedParents? -->
<Grid Margin="{Binding Converter={StaticResource lengthConverter},
RelativeSource={RelativeSource TemplatedParent},
Path=.}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="19" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ToggleButton x:Name="Expander"
Style="{StaticResource ExpandCollapseToggleStyle}"
IsChecked="{Binding Path=IsExpanded,
RelativeSource={RelativeSource TemplatedParent}}"
ClickMode="Press"/>
<ContentPresenter x:Name="PART_Header"
Grid.Column="1"
ContentSource="Header"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/>
</Grid>
</Border>
<!-- the children of the TreeViewItem -->
<ItemsPresenter x:Name="ItemsHost" />
</StackPanel>
<!-- leaving some stuff out here with triggers -->
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
How can I make the HierarchicalDataTemplate fill the Parent property?
I'd scan the visual tree instead.
Here is a simple (even not-so-elegant) solution:
public static class TreeViewItemExtensions
{
public static int GetDepth(this TreeViewItem item)
{
DependencyObject target = item;
var depth = 0;
while (target != null)
{
if (target is TreeView)
return depth;
if (target is TreeViewItem)
depth++;
target = VisualTreeHelper.GetParent(target);
}
return 0;
}
}
Cheers.

Categories

Resources