WPF UI doesn't update textblock in controltemplate - c#

I made a sample XAML and C# for WPF below:
XAML :
<Button Name="btn">
<Button.Template>
<ControlTemplate>
<Grid>
<TextBlock Name="textblock1" Text="sampletext1" />
<Grid>
<ControlTemplate>
</Button.Template>
</Button>
C# :
Grid grid = btn.Template.LoadContent() as Grid;
var textblock = grid.FindName("textblock1") as TextBlock;
textblock.Text = "sampletext2";
I was able to retrieve and change the textblock text in code behind but it seems that the UI doesn't update it. May I know how to solve this?

Change your code in any of the events
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.Loaded += MainWindow_Loaded;
}
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
TextBlock textBlockInTemplate = (TextBlock)btn.Template.FindName("textblock1", btn);
textBlockInTemplate.Text = "SampleText2";
}
}

Your code makes a copy of the value of the text block then assign a property named "Text" to the copy's value. You never actually change the text inside the button. Your text block is called textblock1, textblock was initialized from textblock1 but once that is done they aren't linked together.
It's been awhile since i've used WPF but you need to re-assign the text value to the button using something like this :
textblock1.Text = textblock;
or even simpler:
textblock1.Text = "sampletext2";

Related

Get TextBlock inside Button

I have a Button with a TextBlock embedded inside. When the Button is clicked, I want to be able to fetch the TextBlock inside it and modify it's members.
Here is how my button is setup:
<Button Click="Select_Click" Style="{StaticResource ButtonStyle}" HorizontalAlignment="Left" Padding="0,20,20,20">
<TextBlock Text="My text" FontSize="20" Style="{StaticResource TextBlockStyle}"/>
</Button>
In my code behind I want to be able to access the embedded TextBlock:
public void Select_Click(object sender, RoutedEventArgs e)
{
// Get the `TextBlock` from `sender` here
}
I've taken a look at the visual tree of the Button but I'm not seeing the TextBlock. I called GetVisualChildren() on the Button but I only see a Grid and no way to get to the Textblock.
The content of the Button is stored in its Content property and in your case, the TextBlock is the content of the Button.
public void Select_Click(object sender, RoutedEventArgs e)
{
Button button = (Button)sender;
TextBlock textBlock = (TextBlock)button.Content;
}
Just do some casting and it's pretty simple
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Establish_handlers();
}
void Establish_handlers()
{
Mybutton.Click += Mybutton_Click;
}
private void Mybutton_Click(object sender, RoutedEventArgs e)
{
Button clicked_button = (Button)sender;
TextBlock desired_text = (TextBlock)clicked_button.Content;
Textbox_Show_Button_Content.Text = desired_text.Text;
}
}
<StackPanel>
<Button x:Name="Mybutton">
<TextBlock>Hello</TextBlock>
</Button>
<TextBox x:Name="Textbox_Show_Button_Content"></TextBox>
</StackPanel>

c# - Find and modified image control by gridview selecteditem

I need to change the source of an Image control inside a gridview datatemplate when a click event is raised in uwp. When i click on a car image, this Image needs to be modified and displayed the brand logo. I succeed with that code:
<controls:AdaptiveGridView x:Name="AdaptiveGridViewControl"
animations:ReorderGridAnimation.Duration="350"
Margin="0,12,0,0"
ItemHeight="200"
DesiredWidth="200"
SelectionMode="Single"
IsItemClickEnabled="True"
ItemClick="GridView_ItemClick"
>
<controls:AdaptiveGridView.ItemTemplate>
<DataTemplate x:DataType="data:MyData">
<StackPanel Orientation="Horizontal">
<controls:ImageEx x:Name="ImageExControl"
MaxHeight="200"
IsCacheEnabled="True"
Source="{x:Bind carsPictures}"
Stretch="Fill"
PlaceholderSource="/Assets/placeholder_cover.jpg"
PlaceholderStretch="Uniform"/>
</StackPanel>
</DataTemplate>
</controls:AdaptiveGridView.ItemTemplate>
</controls:AdaptiveGridView>
Thanks to that post : How to access a Control inside the data template in C# Metro UI in the code behind,
i can use FindChildControl(DependencyObject control, string ctrlName) method.
In code behind:
private void GridView_ItemClick(object sender, ItemClickEventArgs e)
{
var newData = (MyData)e.ClickedItem;
ImageEx ex = FindChildControl<ImageEx>(this, "ImageExControl") as ImageEx;
ex.Source = newData.brandLogo;
}
The problem is this gridview contains 30 cars picture and only the first Image control is modified when a click event is raised. I don't know how to use the AdaptiveGridView.SelectedItem to change the clicked Image control.
You need to Get GridViewItem that has been Clicked so that you can change the image of the Clicked Item. Change your ItemClick Event to something like below.
private void GridView_ItemClick(object sender, ItemClickEventArgs e)
{
GridViewItem item = myGridView.ContainerFromItem(e.ClickedItem) as GridViewItem;
MyData newData = (MyData)e.ClickedItem;
ImageEx ex = FindChildControl<ImageEx>(item, "ImageExControl") as ImageEx;
ex.Source = newData.brandLogo;
}
Hope This Helps.

UserControl hidden, Zindex misused?

In my main page I try to show a list of stuff, and on this stuff a userControl as an overlay. In fact I never see it. (In the design view, my userControl is oaky)
XAML MainPage
<Grid>
<Grid x:name="MyPage">
<!-- All this part is visible -->
//Button
//Button
//nice Pic
//Button
</Grid>
<cat:CatPagecontrol x:Name="CatTool" Visibility="Visible" HorizontalAlignment="Center" VerticalAlignment="Center">
<cat:CatPagecontrol.Transitions>
<TransitionCollection>
<PopupThemeTransition/>
</TransitionCollection>
</cat:CatPagecontrol.Transitions>
</cat:CatPagecontrol>
<!-- EDIT I remove the Grid "CatGrid" And the ZIndex -->
</Grid>
I try to switch the ZIndex, no results.
C# File
public MainView()
{
this.CatTool = new CatPagecontrol();
//this.CatTool.Visibility = Visibility.Collapsed;
}
private void showCatSelector()
{
this.CatTool.Visibility = Visibility.Visible;
}
After that I need that one of my buttons show the overlay when clicked.
If you know how to show it, I'm yours. Thanks.
edit : solution find.
Voila !
I've find my problem :
public CatPagecontrol()
{
this.InitializeComponent();
}
I just Initialized in the correct section.

How to add a TextBlock to a Canvas using UserControl class?

here is the XAML...
<Canvas Name="myCanvas">
<TextBlock Name="myBlock" FontFamily="Arial Black" FontSize="100" Foreground="Red" Text="R" Height="105" Width="96" Canvas.Left="61" Canvas.Top="80" /
</Canvas>
I have a partial class that extends a userControl.
public partial class Card : UserControl
I also have a test form that uses this control like this,
public formTest()
{
InitializeComponent();
Card1.drawText();
myCanvas.Children.Add(Card1); //myCanvas is defined in XAML
}
Card Card1 = new Card();
How do add an instance of TextBlock to myCanvas when TextBlock is inside my UserControl? So lets say,
public partial class Card : UserControl
{
private TextBlock txtBlock = new TextBlock();
public Card()
{
txtBlock.Text = "Test";
txtBlock.Foreground = brushFill;
}
public void drawText()
{
//uhhh idk
}
}
In general I don't understand how to get anything to display without defining it in the XAML then adding properties via code. Like this I create an instance of TextBlock, give it some properties... then I'm not sure.
Any help is appreciated. I also know I should be using a User Control but I don't know why?
Your UserControl should also have a XAML file associated, and the TextBlock should be inside that XAML.
The other option would be Card : Control (not UserControl) and then you would need a template.
In neither coase can/should you try to add a TextBlock from inside a Control to myCanvas.
Seems you ought to read up on WPF UserControls and Custom Controls.
If you just want to create a simple TextBlock and add it to the canvas, you'll want to do something like this:
TextBlock textBlock = new TextBlock();
textBlock.Text = "Text";
myCanvas.Children.Add(textBlock);
Then you can manipulate everything you have added to the Canvas via methods in Canvas.Children.

What is the correct way to code the nested methods?

I have created a registration form in silverlight 4, where i have a large number of text-boxes, in front of each text box i have placed a text-block as a required field validator, when any of the textbox left empty while loosing focus, the textblock placed in front of it must become red.
textboxes named textbox1, textbox2 ... and so as the textblocks
the problem is, i do not want code the specific method for each specific textbox, all i want to do is to complete such in just two three methods
here i did some coding which doesn't seems to be correct
private void textBox_LostFocus(object sender, RoutedEventArgs e)
{
var textBox = (TextBox) sender;
if (textbox.Text == "")
{
var textblock = "textblock" + textBox.Name.Remove(0,7);
TextblockColorChange(textblock);
}
}
private void TextblockColorChange(object sender)
{
var textblock = (TextBlock) sender;
textblock.Foreground= new SolidColorBrush(Colors.Red);
}
please suggest some better way to do so..
I'd create a UserControl that contains the TextBlock and the TextBox and use this UserControl everywhere you currently have the TextBlock and TextBox combination. Then this Usercontrol would have the LostFocus logic inside it and update the TextBlock appropriately. This prevents the need to figure out the right name of the control to update.
you need something like this,
XAML part:
<Grid x:Name="LayoutRoot" Background="White">
<StackPanel Orientation="Horizontal" Height="25">
<TextBox Width="150" LostFocus="TextBox_LostFocus"/>
<TextBlock Text="*" Foreground="#FF0000" VerticalAlignment="Center" Margin="10,0,0,0" Visibility="Collapsed"/>
</StackPanel>
</Grid>
C# Part:
private void TextBox_LostFocus(object sender, RoutedEventArgs e)
{
var textbox = sender as TextBox;
if(textbox == null) return;
var stackPanel = textbox.Parent as StackPanel;
if(stackPanel == null) return;
var textBlock = stackPanel.Children.Where(a => a is TextBlock).FirstOrDefault();
if (textBlock == null) return;
if (string.IsNullOrEmpty(textbox.Text)) textBlock.Visibility = Visibility.Visible;
else textBlock.Visibility = Visibility.Collapsed;
}
Whilst I actually prefer Bills approach (although I'd be inclined to use a Templated Control) here is another alternative which is quite fun. In your xaml use this sort of markup:-
<TextBlock Text="Enter Value 1" Foreground="{Binding Tag, ElementName=textBox1, TargetNullValue=Black}" />
<TextBox x:Name="textBox1" LostFocus="txt_LostFocus" />
Your common txt_LostFocus can look like this:-
private void txt_LostFocus(object sender, RoutedEventArgs e)
{
TextBox txt = ((TextBox)sender);
if (String.IsNullOrEmpty(txt.Text))
{
txt.Tag = new SolidColorBrush(Colors.Red);
}
else
{
txt.Tag = null;
}
}
var textblock = "textblock" + textBox.Name.Remove(0,7);
TextblockColorChange(textblock);
This code above will just send a string to TextblockColorChange()
You don't show any other code, but I'm guessing you want to do a FindControl or FindControl like search on that string before passing the result to your code.

Categories

Resources