I created control in WPF from C# and find that control on button click but not found
public MainWindow()
{
InitializeComponent();
TextBox textBox = new TextBox();
textBox.Name = "childTextBox";
TextBoxes.Add(textBox);
StackPanelParent.Children.Add(textBox);
}
private void Button_Click(object sender, RoutedEventArgs e)
{
var findTextBox = (TextBox)this.FindName("childTextBox");
//it's give null
}
XAML Code
<StackPanel Margin="152,103,191,56">
<Label Name="Loader" Visibility="Collapsed">Loader</Label>
<Button Content="Click Me" HorizontalAlignment="Left" Margin="342,199,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>-->
<StackPanel Name="StackPanelParent">
</StackPanel>
<Button Click="Button_Click">Check</Button>
</StackPanel>
When you dynamically create a component they cannot be found by FindName unless you register them first like this:
public MainWindow()
{
InitializeComponent();
TextBox textBox = new TextBox();
textBox.Name = "childTextBox";
TextBoxes.Add(textBox);
StackPanelParent.Children.Add(textBox);
// register name
RegisterName(textBox.Name, textBox);
}
Related
My problem would be, I want to make a menu with MaterialDesign and I want the button style to change when I go to one of the menu items in the menu. However, when I overwrite the MaterialDesign style, I cannot reset it. I wanna make somethin like like this:enter image description here
Thats my menu code:
<Grid>
<StackPanel Orientation="Horizontal" Height="35" VerticalAlignment="Top" >
<Button x:Name="User_B" Content="Users" MinWidth="100" Click="User_B_Click"/>
<Button x:Name="Auto_B" Content="Auto" MinWidth="100" Click="Auto_B_Click"/>
<Button x:Name="Clien_B" Content="Client" MinWidth="100" Click="Clien_B_Click" />
<Button x:Name="Failure_B" Content="Failure" MinWidth="100" Click="Failure_B_Click"/>
<Button x:Name="Settings_B" Content="Settings" MinWidth="100" Click="Settings_B_Click"/>
</StackPanel>
<Frame x:Name="Main" Margin="0,35,0,0" NavigationUIVisibility="Hidden"/>
</Grid>
My c# code:
private void User_B_Click(object sender, RoutedEventArgs e)
{
Style selectstyle = new Style();
selectstyle.TargetType = typeof(Button);
selectstyle.Setters.Add(new Setter(Button.BackgroundProperty, new SolidColorBrush((Color)ColorConverter.ConvertFromString("#303030"))));
selectstyle.Setters.Add(new Setter(Button.ForegroundProperty, new SolidColorBrush((Color)ColorConverter.ConvertFromString("#d50000"))));
User_B.Style = selectstyle;
Auto_B.Style = null;
}
private void Auto_B_Click(object sender, RoutedEventArgs e)
{
Style selectstyle = new Style();
selectstyle.TargetType = typeof(Button);
selectstyle.Setters.Add(new Setter(Button.BackgroundProperty, new SolidColorBrush((Color)ColorConverter.ConvertFromString("#303030"))));
selectstyle.Setters.Add(new Setter(Button.ForegroundProperty, new SolidColorBrush((Color)ColorConverter.ConvertFromString("#d50000"))));
Auto_B.Style = selectstyle;
User_B.Style = null;
}
and this is how it looks now:enter image description here
First you need to do this in all of your pages :
MainWindow mw = null;
public Employees(MainWindow mw)
{
InitializeComponent();
this.mw = mw;
}
Create a null object for your MainWindow , than give a parameter to your Page method , then in the method , you declare the MainWindow like I show you in the code.
After you done with this , then you need to go to the MainWindow.xaml.cs and you have to do this:
public MainWindow()
{
InitializeComponent();
employees = new Employees(this);
Presenter.Content = employees;
}
Employees employees = null;
Create a null object for your Page , and in the MainWindow method you have to declare the Page like this.
After that , you just need a Loaded and an Unloaded event to your page :
private void Page_Loaded(object sender, RoutedEventArgs e)
{
mw.EmployeesButton.Background = (Brush)new BrushConverter().ConvertFrom("#006B60");
}
private void Page_Unloaded(object sender, RoutedEventArgs e)
{
mw.EmployeesButton.Background = (Brush)new BrushConverter().ConvertFrom("#009688");
}
You can use any color you want , I hope its helps :D
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>
How can I show a tooltip in code-behind? The code below defines my question better. Obviously I don't want the code to check for mouse position etc, just how to display the tooltip.
private void UIElement_OnMouseMove(object sender, MouseEventArgs e)
{
// if mouse position equals certain coordinates show the tooltip
}
Try like this:
if (control.ToolTip != null)
{
// Main condition
if (control.ToolTip is ToolTip)
{
var castToolTip = (ToolTip)control.ToolTip;
castToolTip.IsOpen = true;
}
else
{
toolTip.Content = control.ToolTip;
toolTip.StaysOpen = false;
toolTip.IsOpen = true;
}
}
The Main condition necessary, because ToolTip for Control can be set in two approaches:
First approach
<Button Name="TestButton"
ToolTip="TestToolTip" />
This approach is most common. In this case, the content of the ToolTip will object and not type of ToolTip.
Second approach
<Button Name="TestButton"
Content="Test">
<Button.ToolTip>
<ToolTip>TestToolTip</ToolTip>
</Button.ToolTip>
</Button>
Is the same as this:
<Button Name="TestButton"
Content="Test">
<Button.ToolTip>
TestToolTip
</Button.ToolTip>
</Button>
In this case, the Content type of ToolTip will be Tooltip. Note that in the second case, the object automatically fills ToolTip object on line TestToolTip, hence this approach will work a bit slower.
Therefore, this check is needed to avoid an exception when we try to assign to the ToolTip the content of the ToolTip type here:
toolTip.Content = control.ToolTip;
Below is a full example:
XAML
<Grid>
<Button Name="TestButton"
Width="100"
Height="25"
Content="Test"
ToolTip="TestToolTip" />
<Button Name="ShowToolTip"
VerticalAlignment="Top"
Content="ShowToolTip"
Click="ShowToolTip_Click" />
</Grid>
Code-behind
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void ShowToolTip_Click(object sender, RoutedEventArgs e)
{
var toolTip = new ToolTip();
if (TestButton.ToolTip != null)
{
if (TestButton.ToolTip is ToolTip)
{
var castToolTip = (ToolTip)TestButton.ToolTip;
castToolTip.IsOpen = true;
}
else
{
toolTip.Content = TestButton.ToolTip;
toolTip.StaysOpen = false;
toolTip.IsOpen = true;
}
}
}
}
I have a list box displaying the names of help topics which can be added to and the names of the topics changed. Originally it was just displaying strings, but to get the inline editing working I changed it to use a custom type consisting of a string and an InEdit property so the UI can determine whether to display the TextBlock or TextBox:
XAML:
<ListBox ItemsSource="{Binding HelpTopics, Mode=TwoWay}"
SelectedValuePath="Description"
SelectedValue="{Binding SelectedPageId, Mode=TwoWay}"
SelectionChanged="ListBox_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<TextBlock Text="{Binding Description, Mode=TwoWay}"
VerticalAlignment="Center"
MouseLeftButtonUp="TopicTextBlock_MouseLeftButtonUp"
Visibility="{Binding InEdit, Converter={StaticResource boolToVisibilityConverter}, ConverterParameter=contra}"/>
<TextBox Text="{Binding Description, Mode=TwoWay}"
Visibility="{Binding InEdit, Converter={StaticResource boolToVisibilityConverter}, ConverterParameter=pro}"
LostFocus="EditTopicTextBox_LostFocus"
HorizontalAlignment="Stretch" VerticalAlignment="Center"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button Margin="5" Content="Add Topic" Command="{Binding AddTopicCommand}"/>
HelpTopics is an ObservableCollection<EditableHelpTopic>.
SelectedPageId is a string.
boolToVisibilityConverter is a converter that does what it says.
What works:
Adding a topic creates a new item and adds it to the list and put the item in to edit mode.
Double clicking on an existing item puts that item into edit mode sets the focus to the TextBox and selects all the text so it can be overwritten.
When the TextBox loses focus the edit is saved and the display returns to the TextBlock.
What doesn't work:
When a new topic is added the TextBox should have focus and the text selected so the user can enter a new name.
So my question is is there a point in the code or an event where I know that the TextBox has been created and is visible so I can set focus and select its contents. I've tried hooking into the SelectionChanged event but when that fires the TextBox hasn't yet been displayed. I also added an event to the OnAddTopicExecute method in the view model which I handled in the view, but again that fired before the TextBox was visible.
Below is the code that supports the above XAML. I've tried to cut it down, but there still seems to be a lot of it, so you can skip this if you're not interested ;)
Code behind:
private DateTime lastClickTime = DateTime.MinValue;
private Point lastClickPosition;
private void TopicTextBlock_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
UIElement element = sender as UIElement;
if ((DateTime.Now - this.lastClickTime).TotalMilliseconds > 300)
{
this.lastClickPosition = e.GetPosition(element);
this.lastClickTime = DateTime.Now;
}
else
{
Point position = e.GetPosition(element);
if (Math.Abs(this.lastClickPosition.X - position.X) < 4 && Math.Abs(this.lastClickPosition.Y - position.Y) < 4)
{
var textBlock = sender as TextBlock;
var editableHelpTopic = textBlock.DataContext as EditableHelpTopic;
editableHelpTopic.InEdit = true;
var parent = textBlock.Parent as Grid;
TextBox textBox = parent.Children.First(c => c.GetType() == typeof(TextBox)) as TextBox;
textBox.Focus();
textBox.SelectAll();
}
}
}
private void EditTopicTextBox_LostFocus(object sender, RoutedEventArgs e)
{
var textBox = sender as TextBox;
var editableHelpTopic = textBox.DataContext as EditableHelpTopic;
editableHelpTopic.InEdit = false;
if (!textBox.Text.Equals(editableHelpTopic.Description))
{
this.editViewModel.RenameTopic(textBox.Text);
}
}
View Model:
public EditViewModel()
{
...
this.AddTopicCommand = new DelegateCommand(this.OnAddTopicExecute, this.OnAddTopicCanExecute);
...
}
where DelegateCommand is an implemetation of ICommand.
private void OnAddTopicExecute(object parameter)
{
var newTopic = new EditableHelpTopic
{
Description = "NewTopic",
InEdit = true
};
this.HelpTopics.Add(newTopic);
this.SelectedPageId = newTopic.Description;
}
Definitions:
public class EditableHelpTopic : INotifyPropertyChanged
{
public bool InEdit { ... }
public string Description { ... }
}
It turned out to be simpler than I thought.
I just needed to add a Loaded event handler to the TextBox:
private void EditTopicTextBox_Loaded(object sender, RoutedEventArgs e)
{
var textBox = sender as TextBox;
var editableHelpTopic = textBox.DataContext as EditableHelpTopic;
if (editableHelpTopic.InEdit)
{
textBox.Focus();
textBox.SelectAll();
}
}
So at the moment my page is currently working with the following code in my cs file. What I need to change is to add an event handler so that when a button is clicked the MainPage_Loaded happens only after this button is clicked.
I understand that the line
this.Loaded += new RoutedEventHandler(MainPage_Loaded);
is currently calling this method to start but when I try and put this code into the button1_click event handler it does not work.
public MainPage()
{
InitializeComponent();
this.Loaded += new RoutedEventHandler(MainPage_Loaded);
}
public void button1_Click(object sender, RoutedEventArgs e)
{
}
private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
var ctx = new HazchemEntities(new Uri("http://devweb.compsci.chester.ac.uk/0808092/CO6009/HazchemService.svc/"));
App.coll = new DataServiceCollection<tblChemical>(ctx);
Lst.ItemsSource = App.coll;
App.coll.LoadCompleted += new EventHandler<LoadCompletedEventArgs>(coll_LoadCompleted);
var qry = "/tblChemicals?$filter UNNumber = eq'" + Search.Text + "'";
App.coll.LoadAsync(new Uri(qry, UriKind.Relative));
if (!App.ViewModel.IsDataLoaded)
{
App.ViewModel.LoadData();
}
}
Here is the XAML code that I am using.
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock x:Name="ApplicationTitle" Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PageTitle" Text="page name" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
<TextBox x:Name="Search" Height="72" Margin="-4,0,50,0" Text="TextBox" VerticalAlignment="Top" Width="350" HorizontalAlignment="Left"/>
<Button Content="Go" Height="72" HorizontalAlignment="Left" Margin="350,0,0,0" Name="button1" VerticalAlignment="Top" Width="100" Click="button1_Click" />
</StackPanel>
What do I need to put into the button1_Click event to make it start the mainpage_loaded only when this button is clicked?
Thanks
You seem to have misunderstood something... This line:
this.Loaded += new RoutedEventHandler(MainPage_Loaded);
is not causing the void MainPage_Loaded(object sender, RoutedEventArgs e) function to be called immediately. It is registering a handler for that event - when the MainPage has finished loading it internally fires the Loaded event, in turn the event handler gets called.
Setting up that handler in the button1_Click also makes no sense - your page has already well and truly loaded by the time a button can be clicked.
If you have some functionality in the MainPage_Loaded function that you want the button1_Click to also use then you should refactor it out into a separate function that they can both call.
You're assigning the EventHandler to the MainPage Loaded event instead of to the button click.
In the constructor, try this.button1.OnClick += new RoutedEventHandler(MainPage_Loaded);
add the following code to button1_Click
MainPage_Loaded(sender,e);