I am trying to access a control from a control's context menu's control template.My xaml is :
<Button x:Name="button1" ContextMenuService.Placement="top" Content="Button" HorizontalAlignment="Left" Margin="2,543,0,0" VerticalAlignment="Top" Width="75" Grid.ColumnSpan="2">
<Button.ContextMenu>
<ContextMenu x:Name="btconmn" >
<ContextMenu.Template>
<ControlTemplate>
<Grid x:Name="newgrid" Width="183" Height="190">
<Rectangle Fill="#FF263349" x:Name="newfolder" HorizontalAlignment="Left" VerticalAlignment="Top" Width="179" Height="32" Margin="2,1,0,0"/>
</Grid>
</ControlTemplate>
</ContextMenu.Template>
</ContextMenu>
</Button.ContextMenu>
</Button>
Here i'm trying to access the newfolder rectangle. So far i tried :
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
var template = btconmn.Template;
var myControl = (Rectangle)template.FindName("newfolder", btconmn);
}
which returns a null reference exception.Any help ?
WPF controls usually don't load until they are needed, so in your case the earliest point at which you can access the rectangle would be after the button's contextmenu is loaded (which happens immediately before it opens for the first time):
Add this to your XAML:
<ContextMenu x:Name="btconmn" Loaded="Btconmn_OnLoaded">
And this in your code behind:
private void Btconmn_OnLoaded(object sender, RoutedEventArgs e)
{
var template = btconmn.Template;
var myControl = (Rectangle)template.FindName("newfolder", btconmn);
}
Related
I have a TextBlock that is inside a Control Template. I want to change the Text for said TextBlock with the Text value of a TextBox. The value is meant to be set within a button click event however, with the way I've tried to do this it doesn't work. The click event will give out an error stating that text is null.
I am new to WPF and would appreciate any help.
XAML for Control Template:
<Window.Resources>
<ControlTemplate x:Key="panel" TargetType="Button">
<Grid>
<Rectangle x:Name="rectangle" Width="auto" Height="55" RadiusX="10" RadiusY="10"
Fill="White">
</Rectangle>
<TextBlock x:Name="txtBlk" Text="" Margin="10,10,0,0" />
</Grid>
</ControlTemplate>
</Window.Resources>
C# for Button_Click event:
private void panelBtn_Click(object sender, RoutedEventArgs e)
{
var text = (TextBlock)this.Template.FindName("txtBlk", this);
text.Text = txtBox.Text;
}
You should reference the template of the button like this..
private void panelBtn_Click(object sender, RoutedEventArgs e)
{
if (sender is Button btn)
{
var text = btn.Template.FindName("txtBlk", btn) as TextBlock;
text.Text = txtBox.Text;
}
}
#MuhammadSulaiman answered you correctly, but I would suggest that you change the implementation.
Rather than looking for an element in a template, it's better to add a resource to which this element will refer and change this resource.
<Window.Resources>
<sys:String x:Key="button.Text">Some Text</sys:String>
<ControlTemplate x:Key="panel" TargetType="Button">
<Grid>
<Rectangle x:Name="rectangle" Width="auto" Height="55" RadiusX="10" RadiusY="10"
Fill="White">
</Rectangle>
<TextBlock x:Name="txtBlk"
Text="{DynamicResource button.Text}"
Margin="10,10,0,0" />
</Grid>
</ControlTemplate>
</Window.Resources>
private void panelBtn_Click(object sender, RoutedEventArgs e)
{
if (sender is FrameworkElement elm)
{
elm.Resources["button.Text"] = txtBox.Text;
}
}
You can also change the initial text in XAML:
<Button Template="{DynamicResource panel}">
<Buttun.Resources>
<sys:String x:Key="button.Text">Other Text</sys:String>
</Buttun.Resources>
</Buttun>
In the same way, you can set a common initial text for all buttons located in one common container, through the resources of this container.
I have the code in XAML:
<Button Grid.Column="0" Grid.Row="1" x:Name="btnSete" Click="btn_Click">
<ContentControl.Content>
<Viewbox Margin="3">
<TextBlock Text="7"/>
</Viewbox>
</ContentControl.Content>
</Button>
And code behind:
private void btn_Click(object sender, RoutedEventArgs e)
{
Button btn = (Button)e.Source;
txbDisplay.Text = btn.Content.ToString();
}
how do I get the value of <TextBlock Text="7"/> in btn_Click?
Based on your XAML, btn.Content should be the instance of the Viewbox. Then the Child property of the Viewbox should be your TextBlock.
So you should be able to do this (inside your button click event handler):
var viewBox = (Viewbox)btn.Content;
var textBlock = (TextBlock)viewBox.Child;
var text = textBlock.Text; // This is the value you were looking for
txbDisplay.Text = text;
Also, just as a helpful note, the <ContentControl.Content> ... </ContentControl.Content> part of your XAML is superfluous. That block could just be written as:
<Button Grid.Column="0" Grid.Row="1" x:Name="btnSete" Click="btn_Click">
<Viewbox Margin="3">
<TextBlock Text="7"/>
</Viewbox>
</Button>
See the "XAML Content Properties" section on this page for more information why that is if you're not sure.
I have a control template in page Layout as following.
<Grid x:Name="LayoutRoot">
<Grid.Resources>
<ControlTemplate x:Key="myTemplate" TargetType="esri:MapTip">
<Border CornerRadius="10" Background="#DDFFEEEE" BorderThickness="4" BorderBrush="#99FF0000">
<StackPanel Background="#DDFFFFFF">
<sdk:TabControl Height="180" Margin="5" Name="tabControl1" Width="300">
<sdk:TabItem Header="Info" Name="infoTab">
<TextBlock x:Name="cityInfoTxt" Tag="{Binding [City_ID]}"/>
</sdk:TabItem>
</sdk:TabControl>
</StackPanel>
</Border>
</ControlTemplate>
In code behind how can I access the ??
I tried this,
private void button1_Click(object sender, RoutedEventArgs e)
{
var te = this.LayoutRoot.Resources["myTemplate"] as ControlTemplate;
}
but can not access the textblock in the tab control.
override the method OnAplyTemplate() on code behind and try to find your component.
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
var myTextBlock = GetTemplateChild("cityInfoTxt") as TextBlock;
}
Hope it helps
I have this data grid where I am placing all my buttons
<Grid x:Name="ButtonGrid" HorizontalAlignment="Left" Margin="0,90,0,4" Width="186">
<Button x:Name="B1" Content="B1" Height="18" Margin="73,0,59,16" VerticalAlignment="Bottom" Click="B1"/>
<Button x:Name="B2" Content="B2" Height="18" Margin="0,0,-2,16" VerticalAlignment="Bottom" Click="B2_Click" HorizontalAlignment="Right" Width="57"/>
</Grid>
I have the grid collapased on start. But when a button {testGrid} is clicked, I want the grid to ne visible.
Here is my code
namespace project.Test
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
}
EDUTED
private void testGrid_Click(object sender, System.Windows.RoutedEventArgs e)
{
FrameworkElement ButtonGrid = (sender as FrameworkElement).FindName("ButtonGrid") as FrameworkElement;
if ( ButtonGrid.Visibility == System.Windows.Visibility.Collapsed)
ButtonGrid.Visibility = System.Windows.Visibility.Visible;
else
ButtonGrid.Visibility = System.Windows.Visibility.Collapsed;
}
}
}
I think if you move your Grid outside of your DataTemplate it will work. :)
However if you really need to put it in a DataTemplate, as long as your Button is at the same level as the Grid, you should still be able to find it.
Say your xaml code looks like this,
<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="controlstoryboardactionrefissue.MainPage" Width="640" Height="480">
<UserControl.Resources>
<DataTemplate x:Key="DataTemplate1">
<Grid x:Name="myGrid" Height="128" Background="#FFE7C0C0" Width="333">
<Button x:Name="myButton" Content="Button" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75" Margin="31,29,0,0" Click="myButton_Click" />
</Grid>
</DataTemplate>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White">
<ContentControl HorizontalAlignment="Left" VerticalAlignment="Top" Margin="175,198,0,0" ContentTemplate="{StaticResource DataTemplate1}" />
</Grid>
</UserControl>
Then the code behind,
private void myButton_Click(object sender, System.Windows.RoutedEventArgs e)
{
var myButton = (Button)sender;
var grid = myButton.Parent as Grid;
if (grid != null)
{
// do stuff
}
}
Hope it helps. :)
I have the listBox and a ObservableCollection. The listBox.ItemSource (listNotify.ItemSource) is set to that ObservableCollection (errosList).
The problem that i have is that i don`t know how to remove the correct element from errorsList when the user click on the button with content x from listBox. For the item of the listBox i use a ItemTemplate, inside a stackPanel and in stackPanel i have a button.
Bellow is the XAML code:
<ListBox x:Name="listNotify">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Height="35">
<Image Height="16" Source="/Template;component/Resources/error.png" Stretch="Fill" VerticalAlignment="Top" Width="16"/>
<StackPanel Orientation="Vertical">
<HyperlinkButton Content="{Binding ErrorHeader}" HorizontalAlignment="Left" Height="16" Width="125"/>
<TextBlock Text="{Binding ErrorMessage}" HorizontalAlignment="Left" Width="405" d:LayoutOverrides="VerticalAlignment" />
</StackPanel>
<Button Content="x" Width="20" Height="20" Click="removeError_Click"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
The code is from a silverlight 4 project.
Thanks.
private void removeError_Click(object sender, RoutedEventArgs e) {
FrameworkElement fe = sender as FrameworkElement;
if (null != fe) {
_observableCollection.Remove((YourType)fe.DataContext);
}
}
Should do what your looking for. Replace YourType with the type you declared in the ObservableCollectiion.
Don't you have an ID-like property in your Items of the errorsList-Collection? Then you could use the Tag-Property of the Button to archieve this:
<Button Content="x" Width="20" Height="20" Tag="{Binding ID}" Click="Button_Click" />
and in the click-event of the button:
string id = ((Button) sender).Tag.ToString();
var itemToRemove = errorsList.Where(x => x.ID == id).First();
errorsList.Remove(itemToRemove);
Hope that helps