Adding Child Element to your Customize Panel - c#

I am making a customized panel in which I can add any and many elements as I can, but I want to add child elements dynamically from main.xaml ,I am not even able to access that panel in main.xaml why is it so ??
I am making use of custom template in making my customize Panel.
Library.cs
class Modal_Main : Window
{
Rectangle rect = new Rectangle();
Grid gr = new Grid();
public Modal_main()
{
this.WindowState = WindowState.Maximized;
this.AllowsTransparency = true;
this.WindowStyle = WindowStyle.None;
this.Background = Brushes.Black;
this.Opacity = 0.5;
this.WindowStartupLocation = WindowStartupLocation.CenterScreen;
this.AddChild(gr);
rect.Margin = new Thickness(350, 100, 350, 100);
rect.Fill = Brushes.White;
rect.RadiusX = 5;
rect.RadiusY = 5;
rect.Name = "rectangle";
this.MouseLeftButtonDown += Modal_main_MouseLeftButtonDown;
gr.Children.Add(rect);
this.Show();
}
private void Modal_main_MouseLeftButtonDown(object sender, RoutedEventArgs e)
{
if(this.rect.IsMouseOver == false)
this.Close();
}
I want to use this panel something like this in Main.xaml.So that when I add a child element inside Model_Main then that change is directly reflected in my Modal_Main class
Main.xaml
<my_namespace:Modal_Main >
<Button> My_test_button </Button>
<!--I want this button element to appear in my Modal_Main class when i add this child elements here -->
</my_namespace:Modal_Main>

It looks like you want to create your own custom template for your window. We do this via ControlTemplate of the Window. so set the style of window to blow:
<Window>
<Window.Style>
<Style TargetType="{x:Type Window}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Window}">
<Grid>
<!-- Actual Window Content -->
<AdornerDecorator DockPanel.Dock="Bottom">
<ContentPresenter />
</AdornerDecorator>
</DockPanel>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Style>
<Grid>
/// any childs you want to add in your window's content.
<Grid>
and a complete sample:
<!-- Title bar separator-->
<Border Height="1"
DockPanel.Dock="Top"
Background="{DynamicResource
MainWindowTitleBarSeparator}" />
<!-- Actual Window Content -->
<AdornerDecorator DockPanel.Dock="Bottom">
<ContentPresenter />
</AdornerDecorator>
</DockPanel>
</Border>
</Grid>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource=
{RelativeSource Self}, Path=Maximized}"
Value="False">
<Setter TargetName="MaximizeRestoreImage"
Property="Source"
Value="/MixModes.Synergy.Resources;
component/Resources/Maximize.png" />
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Style>
<Grid>
/// any childs you want to add in your window's content.
<Grid>
</Window>
also you can define the Style with x:Key="MyWindowCustomTemplate" in a seperate ResourceDictionary file, then set the Window's Style property to {StaticResource Key=MyWindowCustomTemplate}.

Related

accessing control item when given inner template element

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);
}

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;
}

Show contents as per the selected tabitem in WPF

I have an application named App Window. In which i need to display the installed apps in the tab items. Each tab item contains the data about its corresponding application. If a new app installed, then window will create a new tab item for the newly installed app.
*I have done upto creating a new tab item as per the installed applications.
Code i used:
private List<TabItem> _tabItems;
private TabItem _tabAdd;
try
{
_tabItems = new List<TabItem>();
InstalledApps.DataContext = _tabItems;
InstalledApps.SelectedIndex = 0;
if (A Installed)
this.AddTabItem("A");
if (B Installed)
this.AddTabItem("B");
}
catch (Exception ex)
{
}
private TabItem AddTabItem(string AppName)
{
int count = 1;
// create new tab item
TabItem tab = new TabItem();
tab.Header = AppName;
string tabName = AppName.ToLower();
tab.Name = tabName;
tab.HeaderTemplate = InstalledApps.FindResource("TabHeader") as DataTemplate;
TextBox txt = new TextBox();
txt.IsReadOnly = true;
tab.Content = txt;
_tabItems.Insert(count - 1, tab);
return tab;
}
Xaml:
<TabControl Height="555" HorizontalAlignment="Left" Margin="0,-27,0,0" Name=" InstalledApps " ItemsSource="{Binding}" BorderThickness="0,0,0,0" SelectionChanged=" InstalledApps_SelectionChanged" VerticalAlignment="Top" Width="992" Grid.ColumnSpan="3" Grid.RowSpan="4">
<TabControl.Resources>
<Style TargetType="TabItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TabItem">
<Grid Name="Panel">
<ContentPresenter x:Name="ContentSite" VerticalAlignment="Center"
HorizontalAlignment="Center" ContentSource="Header" Margin="80,10" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Panel" Property="Background" Value="#FFEFEFEF" />
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Setter TargetName="Panel" Property="Background" Value="#FFE0E0E0" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding Items.Count, RelativeSource={RelativeSource Self}}" Value="0">
<Setter Property="Visibility" Value="Hidden" />
</DataTrigger>
</Style.Triggers>
</Style>
<DataTemplate x:Key="TabHeader" DataType="TabItem">
<DockPanel>
<TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType=TabItem }, Path=Header}" />
</DockPanel>
</DataTemplate>
</TabControl.Resources>
</TabControl>
My requirement is:
While i am selecting anyone tab from the listed tab items, then it should show its corresponding contents(logo, app name) in is content part.
Thanks in advance,
Kathiresan S.
Create class representing the data you want to display. e.g:
public class AppDetails {
public Uri Logo { get; set; }
public string AppName { get; set; }
//etc
}
then set the AppDetails to TabItem.Content and define TabItem.ContentTemlate similarly as you did with HeaderTemplate.
tab.ContentTemplate = InstalledApps.FindResource("TabContent") as DataTemplate;
tab.Content = new AppDetails{ ... };
alternatively, you can skip ContentTemplate and assign some FrameworkElement (e.g. custom UserControl) directly to the tab content:
tab.Content = new AppDetailsUserControl(AppName, Logo);
Ans to If a new app installed, then window will create a new tab item for the newly installed app.
you should bind the DataContext of TabControl to ObservableCollection so that any new Tabitem added by backend will be shown UI directly.
Ans to While i am selecting anyone tab from the listed tab items, then it should show its corresponding contents(logo, app name) in is content part
You should set the content tab.Content to a UserControl or Model (if Model then define DataTemplate in ResourceDictionary). UserControl or DataTemplate can define what information should be displayed at what control and their visual hierarchy.

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

Change property of component from template based on parent

I want to use the same style for two controls, just change two background colors that are deep in its hierarchy.
I have a TextBox, a style for its ScrollViewer, a style and a template for its ScrollBar with a Background for its Border and a style for its Thumb with a Background for its Border.
How can I change The two backgrounds (programmatically or not) using only the TextBox?
.........
..........
..........
<!-- ScrollBar Style -->
<Style x:Key="{x:Type ScrollBar}" TargetType="ScrollBar">
....
<Style.Triggers>
<Trigger Property="Orientation" Value="Horizontal">
....
<Setter Property="Template" Value="{StaticResource HorizontalScrollBarTemplate}"/>
....
</Trigger>
</Style.Triggers>
</Style>
<!-- Horizontal Scrollbar Template -->
<ControlTemplate x:Key="HorizontalScrollBarTemplate" TargetType="{x:Type ScrollBar}">
<Grid Background="{StaticResource ScrollBackroundBrush}">
<Track Name="PART_Track">
<Track.Thumb>
<Thumb Style="{StaticResource ScrollBarThumb}"/>
</Track.Thumb>
</Track>
</Grid>
</ControlTemplate>
<!-- Thumb Style -->
<Style x:Key="ScrollBarThumb" TargetType="{x:Type Thumb}">
....
<Setter Property="Template">
....
<Border
....
Background="{StaticResource ScrollThumbBrush}"/>
....
</Setter>
</Style>
Is there a way to change the two backgrounds (to use this color and another same scrollviewer on another control perhaps with another color) without rewriting the whole code?
For example to have its style and write:
TextBox tb1 = new TextBox();
tb1.Style = /*style*/
tb1.BackgroundOfScroll = /*brush11*/
tb1.BackgroundOfThumb = /*brush12*/
TextBox tb2 = new TextBox();
tb2.Style = /*style*/
tb2.BackgroundOfScroll = /*brush21*/
tb2.BackgroundOfThumb = /*brush22*/
I made corresponding example. If you had only one color to set you could use Tag property since it is DependencyProperty. Create then two attached properties and get to them as follows:
<Button local:Color.CustomBackground="CadetBlue">
<Button.Template>
<ControlTemplate TargetType="Button">
<ContentPresenter>
<ContentPresenter.ContentTemplate>
<ItemContainerTemplate>
<Border Width="50" Height="{Binding RelativeSource={RelativeSource Self}, Path=Width}"
Background="{Binding RelativeSource={RelativeSource AncestorType=Button}, Path=(local:Color.CustomBackground)}">
</Border>
</ItemContainerTemplate>
</ContentPresenter.ContentTemplate>
</ContentPresenter>
</ControlTemplate>
</Button.Template>
</Button>
C#
public class Color : DependencyObject
{
private static readonly DependencyProperty CustomBackgroundProperty =
DependencyProperty.RegisterAttached("CustomBackground", typeof(SolidColorBrush), typeof(Color),
new PropertyMetadata(null));
public static void SetCustomBackground(DependencyObject obj, SolidColorBrush color)
{
obj.SetValue(CustomBackgroundProperty, color);
}
public static SolidColorBrush GetCustomBackground(DependencyObject obj)
{
return (SolidColorBrush)obj.GetValue(CustomBackgroundProperty);
}
}

Categories

Resources