How to access controls, which are in the ControlTemplate - c#

In my WP8 appliciation's App.xaml file I've defined ControlTemplate as following:
<Application.Resources>
<ControlTemplate x:Name="AddReminderDialog">
<Canvas HorizontalAlignment="Center" Height="320" Width="260"
VerticalAlignment="Center" Background="White" Margin="110,178,110,238">
<TextBlock Foreground="Black" Text="Напомнить" FontSize="15" HorizontalAlignment="Center" Canvas.Left="92" Canvas.Top="38" />
<Button Name="btn1HourBef" BorderThickness="0" Click="NotificationButtonClick" Background="Black" Content="За час" Width="260" FontSize="15" Height="60" Margin="0,70,0,0"/>
<Button Name="btn30MinBef" BorderThickness="0" Click="NotificationButtonClick" Background="Black" Content="За 30 минут" Width="260" FontSize="15" Height="60" Margin="0,130,0,0"/>
<Button Name="btnOnArrDept" BorderThickness="0" Click="NotificationButtonClick" Background="Black" Content="По прилету/вылету" Width="260" FontSize="15" Height="60" Margin="0,190,0,0"/>
<Button Name="btnCancel" BorderThickness="0" Click="NotificationButtonClick" Background="Black" Content="Отменить" Width="260" FontSize="15" Height="60" Margin="0, 250, 0, 0" Visibility="Collapsed"/>
</Canvas>
</ControlTemplate>
</Application.Resources>
I use it as a template of popup as following
private void Image_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
var image = sender as Image; //get the sender iamge
var modelItem = image.DataContext; //get image's data context
const double width = 260;
const double height = 280;
//get the flight id from image's tag property(which was binded in flightInfoDataTemplate)
flightID = Convert.ToString(image.Tag);
//define content for popup
var content = new ContentControl()
{
Width = width,
Height = height,
Background = new SolidColorBrush(Colors.Transparent)
};
//set the template of content to the contentTemplate, which was defined in app.xaml
content.Template = (ControlTemplate)Resources["AddReminderDialog"];
//set popup's datacontext to the image's datacontext
content.DataContext = modelItem;
//popup's child property is setting to our content
popup.Child = content;
popup.Height = height;
popup.Width = width;
popup.VerticalOffset = Application.Current.RootVisual.RenderSize.Height / 2 - height / 2;
popup.HorizontalOffset = Application.Current.RootVisual.RenderSize.Width / 2 - width / 2;
popup.IsOpen = true;
}
I use this popup to set notification. When user taps the image in the first time the btnCancel button should be invisible, because there is nothing to cancel. When the image is tapped the second time, btnCancel should become visible to cancel the notification.
I've set button visibility to collapsed by default. But I have not idea how to access that button in the code behind to make it visible.
So my question is how can I change button's visibility settings in the code behind?

You can do something like this,
private void SearchElement(DependencyObject targeted_control)
{
var count = VisualTreeHelper.GetChildrenCount(targeted_control); // targeted_control is the Canvas
if (count > 0)
{
for (int i = 0; i < count; i++)
{
var child = VisualTreeHelper.GetChild(targeted_control, i);
if (child is Button ) // specific button control
{
// do your logic
}
}
}
}

Related

Set Font size to richtexblock in uwp dynamically

I have the following code:
<ScrollViewer x:Name="swipeBetweenPages" Grid.Row="1">
<Pivot DataContext="{StaticResource ViewModel}" x:Name="pivot" Margin="0,-45,0,0"
HeaderTemplate="{StaticResource headerTest}"
ItemTemplate="{StaticResource pivotTemplate}" ItemsSource="{Binding Articles}" SelectionChanged="pivot_SelectionChanged">
</Pivot>
</ScrollViewer>
<Page.Resources>
<ViewModels:ArticleViewModel x:Key="ViewModel" />
<DataTemplate x:Key="headerTest">
</DataTemplate>
<DataTemplate x:Key="pivotTemplate">
<StackPanel Margin="-15 0 -15 0">
<Grid>
<Grid.Background>
<ImageBrush AlignmentX="Center" AlignmentY="Center" ImageSource="Assets/PlaceHolder.jpg"></ImageBrush>
</Grid.Background>
<Image q42controls:ImageExtensions.CacheUri="{Binding ImageURL}" Tag="{Binding ImageURL}" Tapped="ImageView"></Image>
</Grid>
<StackPanel Background="White">
<TextBlock x:Name="HeadLine" Text="{Binding HeadLine}"
Margin="10 5 0 -5" TextWrapping="Wrap"
FontSize="20" Foreground="Black"
FontFamily="{StaticResource HeadlineCommonFamiy}"
Pivot.SlideInAnimationGroup="GroupTwo" Height="63"
FontWeight="Bold" TextTrimming="CharacterEllipsis"/>
<TextBlock Text="{Binding Abstract}" TextWrapping="Wrap" FontSize="15" FontStyle="Italic"
Pivot.SlideInAnimationGroup="GroupTwo" Margin="10 5 0 10"
FontFamily="{StaticResource AbstractCommonFamily}"/>
</StackPanel>
<StackPanel x:Name="descriptionSP" Background="White">
<RichTextBlock IsTextSelectionEnabled="False" x:Name="richTextBlock"
local:Properties.Html="{Binding ArticleDetail}" TextWrapping="Wrap"
Pivot.SlideInAnimationGroup="GroupTwo" Margin="10 5 0 10"
FontFamily="{StaticResource ContentControlThemeFontFamily}">
</RichTextBlock>
</StackPanel>
</StackPanel>
</DataTemplate>
</Page.Resources>
I am trying to set the font size to rich text block in the back end dynamically.
Now, I am trying with the following code in the C# end:
private T FindElementInVisualTree<T>(DependencyObject parentElement) where T : DependencyObject
{
var count = VisualTreeHelper.GetChildrenCount(parentElement);
if (count == 0) return null;
for (int i = 0; i < count; i++)
{
var child = VisualTreeHelper.GetChild(parentElement, i);
if (child != null && child is T)
return (T)child;
else
{
var result = FindElementInVisualTree<T>(child);
if (result != null)
return result;
}
}
return null;
}
RichTextBlock richTextBlock = new RichTextBlock();
StackPanel rootStackPanel = new StackPanel();
StackPanel childStackPanel = new StackPanel();
PivotItem item = (sender as Pivot).ContainerFromItem((sender as Pivot).SelectedItem) as PivotItem;
rootStackPanel = item.ContentTemplate.LoadContent() as StackPanel;
childStackPanel = rootStackPanel.FindName("descriptionSP") as StackPanel;
richTextBlock = rootStackPanel.FindName("richTextBlock") as RichTextBlock;
Paragraph paragraph = new Paragraph();
Run run = new Run();
// Customize some properties on the RichTextBlock.
richTextBlock.IsTextSelectionEnabled = true;
richTextBlock.SelectionHighlightColor = new SolidColorBrush(Windows.UI.Colors.Pink);
richTextBlock.Foreground = new SolidColorBrush(Windows.UI.Colors.Blue);
richTextBlock.FontWeight = Windows.UI.Text.FontWeights.Light;
richTextBlock.FontFamily = new FontFamily("Arial");
richTextBlock.FontStyle = Windows.UI.Text.FontStyle.Italic;
richTextBlock.FontSize = 50;
//run.Text = "This is some sample text to demonstrate some properties.";
paragraph.Inlines.Add(run);
richTextBlock.Blocks.Add(paragraph);
// Add the RichTextBlock to the visual tree (assumes stackPanel is decalred in XAML).
//childStackPanel.Children.Add(richTextBlock);
//rootStackPanel.Children.Add(richTextBlock);
But, it is not affecting the font size.
Please help me.
Thanks.
You can create a Property in your ViewModel or code behind file and use data binding to connect it to the FontSize property.
private double _myFontSize;
public double MyFontSize
{
get{ return _myFontSize; }
set{ _myFontSize = value; }
}
Now inside your data template for the font size of the rich text box,
FontSize="{Binding MyFontSize, ElementName=page/viewModel}"
And remember to use 'INotifyPropertyChanged' to notify the UI when the value of your property changes. This web site provides a guide on implementing 'INotifyPropertyChanged'

How to get controls inside Pivot.ItemTemplate in Pivot in UWP?

I have the following code:
<ScrollViewer x:Name="swipeBetweenPages" Grid.Row="1">
<Pivot DataContext="{StaticResource ViewModel}" x:Name="pivot" Margin="0,-45,0,0"
HeaderTemplate="{StaticResource headerTest}"
ItemTemplate="{StaticResource pivotTemplate}" ItemsSource="{Binding Articles}" SelectionChanged="pivot_SelectionChanged">
</Pivot>
</ScrollViewer>
<Page.Resources>
<ViewModels:ArticleViewModel x:Key="ViewModel" />
<DataTemplate x:Key="headerTest">
</DataTemplate>
<DataTemplate x:Key="pivotTemplate">
<StackPanel Margin="-15 0 -15 0">
<Grid>
<Grid.Background>
<ImageBrush AlignmentX="Center" AlignmentY="Center" ImageSource="Assets/PlaceHolder.jpg"></ImageBrush>
</Grid.Background>
<Image q42controls:ImageExtensions.CacheUri="{Binding ImageURL}" Tag="{Binding ImageURL}" Tapped="ImageView"></Image>
</Grid>
<StackPanel Background="White">
<TextBlock x:Name="HeadLine" Text="{Binding HeadLine}"
Margin="10 5 0 -5" TextWrapping="Wrap"
FontSize="20" Foreground="Black"
FontFamily="{StaticResource HeadlineCommonFamiy}"
Pivot.SlideInAnimationGroup="GroupTwo" Height="63"
FontWeight="Bold" TextTrimming="CharacterEllipsis"/>
<TextBlock Text="{Binding Abstract}" TextWrapping="Wrap" FontSize="15" FontStyle="Italic"
Pivot.SlideInAnimationGroup="GroupTwo" Margin="10 5 0 10"
FontFamily="{StaticResource AbstractCommonFamily}"/>
</StackPanel>
<StackPanel x:Name="descriptionSP" Background="White">
<RichTextBlock IsTextSelectionEnabled="False" x:Name="richTextBlock"
local:Properties.Html="{Binding ArticleDetail}" TextWrapping="Wrap"
Pivot.SlideInAnimationGroup="GroupTwo" Margin="10 5 0 10"
FontFamily="{StaticResource ContentControlThemeFontFamily}">
</RichTextBlock>
</StackPanel>
</StackPanel>
</DataTemplate>
</Page.Resources>
How to get the RichTextBlock control inside the stackpanel?
Now, I am trying with the following code in the C# end:
private T FindElementInVisualTree<T>(DependencyObject parentElement) where T : DependencyObject
{
var count = VisualTreeHelper.GetChildrenCount(parentElement);
if (count == 0) return null;
for (int i = 0; i < count; i++)
{
var child = VisualTreeHelper.GetChild(parentElement, i);
if (child != null && child is T)
return (T)child;
else
{
var result = FindElementInVisualTree<T>(child);
if (result != null)
return result;
}
}
return null;
}
RichTextBlock richTextBlock = new RichTextBlock();
StackPanel rootStackPanel = new StackPanel();
StackPanel childStackPanel = new StackPanel();
PivotItem item = (sender as Pivot).ContainerFromItem((sender as Pivot).SelectedItem) as PivotItem;
rootStackPanel = item.ContentTemplate.LoadContent() as StackPanel;
childStackPanel = rootStackPanel.FindName("descriptionSP") as StackPanel;
richTextBlock = rootStackPanel.FindName("richTextBlock") as RichTextBlock;
Paragraph paragraph = new Paragraph();
Run run = new Run();
// Customize some properties on the RichTextBlock.
richTextBlock.IsTextSelectionEnabled = true;
richTextBlock.SelectionHighlightColor = new SolidColorBrush(Windows.UI.Colors.Pink);
richTextBlock.Foreground = new SolidColorBrush(Windows.UI.Colors.Blue);
richTextBlock.FontWeight = Windows.UI.Text.FontWeights.Light;
richTextBlock.FontFamily = new FontFamily("Arial");
richTextBlock.FontStyle = Windows.UI.Text.FontStyle.Italic;
richTextBlock.FontSize = 50;
//run.Text = "This is some sample text to demonstrate some properties.";
//Add the Run to the Paragraph, the Paragraph to the RichTextBlock.
paragraph.Inlines.Add(run);
richTextBlock.Blocks.Add(paragraph);
// Add the RichTextBlock to the visual tree (assumes stackPanel is decalred in XAML).
//childStackPanel.Children.Add(richTextBlock);
//rootStackPanel.Children.Add(richTextBlock);
But I am not able to get the control RichTextBlock. I am getting a null value.
Please help me.
Thanks.
You can use ContentTemplate of PivotItem to get the template of PivotItem for example like this:
PivotItem item = (sender as Pivot).ContainerFromItem((sender as Pivot).SelectedItem) as PivotItem;
var rootStackPanel = item.ContentTemplate.LoadContent() as StackPanel;
var richtb = rootStackPanel.FindName("richtb") as RichTextBlock;
And I firstly gave a name to the RichTextBlock as "richtb".
The code you provided searches the tree for the first matching control of the given type. This means, that what you get in return is the first StackPanel in the XAML definition, but the RichTextBlock in the second one.
Why don't you directly do this, instead of searching for the StackPanel:
var richTextBlock = FindElementInVisualTree<RichTextBlock>(item);
This will return the RichTextBlock directly, because the FindElementInVisualTree method is searching down the tree recursively.

Dynamically added controls in stackpanel is not visible in wpf c#

I am dynamically adding textboxes based on a button click inside the stackpanel.But the textboxes are not visible in the UI .
Here is the code used for creating textboxs inside stackpanel.
public void GenerateControls()
{
TextBox txtNumber = new TextBox();
txtNumber.Name = "txtNumber";
txtNumber.Text = "1776";
txtNumber.Background= Brushes.Red;
panel1.Children.Add(txtNumber);
}
why its not visible..??and here is the XAML part of stackpanel
<StackPanel Name="panel1" Grid.Column="1" HorizontalAlignment="Left" Height="151" Margin="427,60,0,0" Grid.Row="2" VerticalAlignment="Top" Width="216">
<StackPanel Height="144">
</StackPanel>
</StackPanel>
If you are going to be adding controls dynamically, do not restrict the height (or even width) of the container you are adding to.
Update your XAML to have auto height/width.
<StackPanel Name="panel1"
Grid.Column="1"
Height="Auto"
Width="Auto"
Margin="427,60,0,0"
Grid.Row="2"
VerticalAlignment="Top"
HorizontalAlignment="Left" >
<StackPanel Height="144">
</StackPanel>
</StackPanel>
Also, once you add a new child, make sure you are updating the StackPanel layout.
public void GenerateControls()
{
TextBox txtNumber = new TextBox();
txtNumber.Name = "txtNumber";
txtNumber.Text = "1776";
txtNumber.Background= Brushes.Red;
panel1.Children.Add(txtNumber);
panel1.UpdateLayout();
}
In your xaml code, there is a stackpanel in your 'panel', it will be the 1st child of 'panel'.
And its height is 144px. your 'panel1' is 151 px.
So when you add textboxes into 'panel', they will be displayed behind the 144px stackpanel.
There is only 7px to display them. So they will not display on your window.

Listbox in CustomMessageBox always scrolls up

I've got a weird problem with a listbox, which is placed in a custommessagebox.
Problem: You can't scroll down the list, because a "draggesture" up does the same thing than down. So the only thing I got is the respond-animation when your at the top of the list.
I made a little sample:
<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!--TitlePanel contains the name of the application and page title-->
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}" Margin="12,0"/>
<TextBlock Text="page name" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<Button Background="Bisque" Content="Click Me" Click="Button_Click"></Button>
</Grid>
</Grid>
public partial class MainPage : PhoneApplicationPage
{
// Constructor
public MainPage()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
var source = new string[200];
for (int i = 0; i < source.Length; i++)
{
source[i] = i.ToString();
}
var dialog = new CustomMessageBox()
{
Content = new ListBox(){ItemsSource = source},
RightButtonContent = "Cancel",
LeftButtonContent = "Store",
VerticalContentAlignment = VerticalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center,
Background = new SolidColorBrush(Colors.Black),
HorizontalContentAlignment = HorizontalAlignment.Center,
HorizontalAlignment = HorizontalAlignment.Center
};
dialog.Show();
}
}
And here is the link, if you wanna download it:
https://onedrive.live.com/redir?resid=6B27FD720F1FB58D!15988&authkey=!ACG5krcfzsoBxA8&ithint=folder%2csln
Does anyone has an idea whats going wrong?
Thx for any help.
There is a simple fix for that.. Add a Height to the ListBox. Like this.
var dialog = new CustomMessageBox()
{
Content = new ListBox(){ItemsSource = source, Height = 800},
RightButtonContent = "Cancel",
LeftButtonContent = "Store",
VerticalContentAlignment = VerticalAlignment.Top, // Change to Top
VerticalAlignment = VerticalAlignment.Top, // Change to Top
Background = new SolidColorBrush(Colors.Black),
HorizontalContentAlignment = HorizontalAlignment.Center,
HorizontalAlignment = HorizontalAlignment.Center
};
Change the VerticalContentAlignment and VerticalAlignment to Top so when you set the Height value less than 800 the content is aligned to the top.
just you need to add height for listbox as :
Content = new ListBox(){ItemsSource = source,Height=800}
I do not recommend setting the height, as Daniel Z mentioned you'll lose adaptive design. I managed a better workaround and it worked perfectly for me without setting the height to a static value.
Put the content of the CustomMessageBox in a UserControl. Suppose the xaml content of this control looks like this
<Grid x:Name="LayoutRoot" Background="{StaticResource PhoneBackgroundBrush}">
<!-- your listbox and content here -->
</Grid>
in the code behind, implement the loaded event:
public UserControl1()
{
InitializeComponent();
this.Loaded += UserControl1_Loaded;
}
void UserControl1_Loaded(object sender, RoutedEventArgs e)
{
LayoutRoot.Height = (this.Parent as CustomMessageBox).ActualHeight;
}
By setting the height of the grid, your listbox will automatically adjust its height to fit in. Hope it helps.

Show alternately text and image at the center

Here is piece of my code:
<StackPanel Orientation="Vertical" Grid.Row="0" Grid.Column="0" >
<Image HorizontalAlignment="Center" VerticalAlignment="Center" Visibility="Collapsed" Stretch="None" Name="BImage" Grid.Row="0" Margin="10 100 10 10">
</Image>
<TextBlock Margin="10 0 10 0" Name="InnerContent" FontSize="45" TextWrapping="Wrap" Text=" "/>
What I would like to achieve is to show BImage and InnerContent alternately but text should be always in the center of the image space so that when image is replaced by text, text is in the middle of the space of the image.
And when this is done I would like to add another TextBlock called errorTextBlock and it should be always visible just below BImage or InnerContent according to which one is visible right now.
I hope that it's clear
May be this could help.
public System.Windows.Threading.DispatcherTimer _timer = new System.Windows.Threading.DispatcherTimer();
_timer.Tick += _timer_Tick;
_timer.Interval = new TimeSpan(0,0,1);
_timer.Start();
int second = 0; // a local variable to keep tab on alternate visibility of elements per second in _timer_Tick
void _timer_Tick(object sender, EventArgs e)
{
second++;
if((second % 2) == 0)
{
InnerContent.Visibility = System.Windows.Visibility.Hidden;
BImage.Visibility = System.Windows.Visibility.Visible;
}
else
{
BImage.Visibility = System.Windows.VisibilityHidden;
InnerContent.Visibilty = System.Windows.Visibility.Visible;
}
}

Categories

Resources