Event Binding Using { } [duplicate] - c#

This question already has answers here:
Assigning events in object initializer
(3 answers)
Closed 9 years ago.
I am creating a TextBox in code-behind.
TextBox textBox = new TextBox();
I also have a function:
private void TextBox_Focus(object sender, RoutedEventArgs e)
{
// does something
}
I want to bind TextBox_Focus to TextBox.GotFocus.
Rather than setting each property individually like so
TextBox textBox = new TextBox();
textBox.Width = 100;
textBox.Height = 25;
textBox.Background = Brushes.White;
textBox.Foreground = Brushes.Blue;
textBox.GotFocus += TextBox_Focus;
I prefer using braces (curly brackets) {}:
TextBox textBox = new TextBox()
{
Width = 100,
Height = 25,
Background = Brushes.White,
Foreground = Brushes.Blue
};
However, when I use the braces method, I am unable to bind to events.
I have tried doing the following, but to no avail...
TextBox textBox = new TextBox()
{
Width = 100,
Height = 25,
Background = Brushes.White,
Foreground = Brushes.Blue,
this.GotFocus += TextBox_Focus
};
Question:
Is there a way to event bind using the braces ({}) method?
Update:
The element is being created dynamically, so I cannot use XAML.

No. Object initializers only work to set properties or fields. You're trying to subscribe to an event, which isn't supported in Object initializer syntax.
As other commenters are saying, XAML is the best way to initialize WPF controls.
Apparently Mono though supports what you're asking for. See: Initializing events with initializer syntax

Why not use Xaml, you'll find it is quite flexible.
And also kinda WPF's thing.
<TextBox x:Name="textBox"
Width="100"
Height="25"
Background="White"
Foreground="Blue"
GotFocus="TextBox_Focus" />
As per your comment, you can do what you wish like so:
<ListBox ItemsSource="{Binding MyCollection}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding }"
Width="100"
Height="25"
Background="White"
Foreground="Blue"
GotFocus="TextBox_Focus" />
</DataTemplate>
</ListBox.ItemTemplate>
If you make your Collection an ObservableCollection<T> when you add an item to the collection it will update your list box for you.

Try
EventManager.RegisterClassHandler(typeof(TextBox),TextBox.GotKeyboardFocusEvent, new RoutedEventHandler(yourMethod());

Related

XAML label to C# code for creating dynamic labels [duplicate]

This question already has answers here:
How can I dynamically create a list of label and textboxes in WPF?
(2 answers)
How to generate labels, buttons, Checkboxes and textboxes dynamically in WPF App
(1 answer)
create dynamically label at wpf
(1 answer)
Closed 3 years ago.
I created labels in XAML that are multiline and all lines are centered, tested and working perfectly fine. Now I want to create these labels dynamically but unfortunately I don't know how to do this.
tried setting LineStackingStrategy on MaxHeight, Fontfamily
tried creating new Textblock on fontfamily
XAML Code to reproduce in C# code:
<Label HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Name="btn_02" Height="70" Width="160" BorderBrush="#F0F2A4" BorderThickness="2" Background="Transparent" Foreground="#F0F2A4" FontFamily="Arial" FontSize="13" TextBlock.LineStackingStrategy="BlockLineHeight" TextBlock.LineHeight="17" Content="ORGEL
LADEN" TextBlock.TextAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Top" Margin="0,200,0,0" MouseLeftButtonDown="Btn_02_MouseLeftButtonDown"/>
C# code to create label dynamically:
Label label = new Label()
{
HorizontalAlignment = HorizontalAlignment.Center,
HorizontalContentAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Top,
VerticalContentAlignment = VerticalAlignment.Center,
Name = "orgel" + i.ToString(),
Height = 70,
Width = 160,
BorderBrush = (SolidColorBrush)(new BrushConverter().ConvertFrom("#F0F2A4")),
BorderThickness = new Thickness(2),
Background = Brushes.Transparent,
Foreground = (SolidColorBrush)(new BrushConverter().ConvertFrom("#F0F2A4")),
FontFamily = new FontFamily("Arial"),
FontSize = 13,
Content = orgel,
Margin = new Thickness((columncount * 100), (rowcount * 100), 0, 0)
};
I want to add TextBlock.LineStackingStrategy="BlockLineHeight" TextBlock.LineHeight="17" Content="ORGEL
LADEN" TextBlock.TextAlignment="Center" from XAML to this C# code.
Whenever you want to create UI elements dynamically you should think of a DataTemplate first. Use a ItemsControl to create UI elements simply by adding data to the ObservableCollection that serves as the Binding.Source of ItemsControl.ItemsSource. The DataTemplate is used to define the appearance of the items (a Labelin your case).
Data Templating Overview
ViewModel.cs
class ViewModel : INotifyPropertyChanged
{
private ObservableCollection<string> labelContents;
public ObservableCollection<string> LabelContents
{
get => this.labelContents;
set
{
this.labelContents = value;
OnPropertyChanged();
}
}
// Constructor
public void ViewModel()
{
// Initialize the data binding source of the ListView
this.LabelContents = new ObservableCollection<string>();
}
public void CreateLabelDynamically(string labelText)
{
this.LabelContents.Add(labelText);
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
When executing CreateLabelDynamically() a new label in form of a TextBlock is added to the view.
MainWindow.xaml
<Window>
<Window.DataContext>
<ViewModel />
</Window.DataContext>
<ListView x:Name="SpectrumBars"
ItemsSource="{Binding LabelContents}">
<ListView.ItemTemplate>
<DataTemplate DataType="system:string">
<!-- The DataContext of the TextBlock is the string value contained in LabelContents -->
<TextBlock Text="{Binding}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Window>
It is also recommended to use a TextBlock instead of a Label when possible:
When data binding the Label element's Content property to the String source object, you may experience poor performance.
Avoid Databinding to the Label.Content Property

UWP - Show textbox text highlight while textbox is out of focus

How do I prevent the textbox from hiding the selected text highlight when the textbox loses focus? The following line worked for WPF
textBox1.IsInactiveSelectionHighlightEnabled = true;
but what is the equivalent for UWP?
You can set the SelectionHighlightColorWhenNotFocused property either in Xaml or via code. You can set it to any color you want, I just used binding to make sure it's the same color as the SelectionHighlightColor to make it easy.
<TextBox Style="{StaticResource TextBoxLightStyle}" Name="TextBoxMain"
AcceptsReturn="True"
SelectionHighlightColorWhenNotFocused="{Binding SelectionHighlightColor, ElementName=TextBoxMain, Mode=OneWay}">
</TextBox>
As I know there is no equivalent in UWP for that. One of possible work-around solutions could be to use some image to keep selection highlighted. Here is sample code:
XAML:
<Border BorderThickness="2" BorderBrush="{ThemeResource TextBoxBorderThemeBrush}" Height="164" Width="684">
<TextBox x:Name="textBox" TextWrapping="Wrap" Text="TextBox" BorderThickness="0,0,0,0"/>
</Border>
C#:
private async void TextBox_SelectionChanged(object sender, RoutedEventArgs e)
{
// clear background
textBox.Background = new SolidColorBrush(Windows.UI.Color.FromArgb(255, 255, 255, 255)); ;
// render image
RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap();
await renderTargetBitmap.RenderAsync(textBox);
// set background
textBox.Background = new ImageBrush()
{
ImageSource = renderTargetBitmap
};
}
In focus:
Not in focus:
p.s. I'm updating background on SelectionChanged event, but actually you can create image on that event and update only on LostFocus event. It should be more efficient.

Create binding to string in Resources.resx from code behind

I started by making a label in XAML with its content bound to a string in my resources file. I've implemented localization and confirm that when I change languages, the label's content updates accordingly.
Now I need to do the same from code behind.
Here is a taste of the XAML:
<Grid Background="#FF313131">
<ScrollViewer>
<StackPanel x:Name="GeneralTab_StackPanel">
<WrapPanel VerticalAlignment="Top" Background="{Binding AxisDataColorCode}" Margin="2,2,2,0">
<Label x:Name="lbl_General_MachineType" Content="{Binding GUI_MachineType, Source={StaticResource Resources}}" FontSize="20" />
<Label x:Name="lbl_General_MachineTypeResult" Content="{Binding MachineBaseType}" FontSize="20" />
</WrapPanel>
<WrapPanel....
Attempting to recreate this in code-behind I have the following:
Binding BgColorBinding = new Binding("AxisDataColorCode");
// Something needs to change here. I've tried a bunch of things already with no luck.
Binding GUI_MachineTypeBinding = new Binding("GUI_MachineType");
GUI_MachineTypeBinding.Source = Properties.Resources.GUI_MachineType;
Binding MachineBaseTypeBinding = new Binding("MachineBaseType");
Label Label_MachineType = new Label();
Label_MachineType.Name = "lbl_General_MachineType";
Label_MachineType.FontSize = 20;
// This does not work at all. Help!
Label_MachineType.SetBinding(Label.ContentProperty, GUI_MachineTypeBinding);
// this works! but it's not a binding and doesn't update...
// Label_MachineType.Content = Properties.Resources.GUI_MachineType;
Label Label_MachineTypeResult = new Label();
Label_MachineTypeResult.Name = "lbl_General_MachineTypeResult";
Label_MachineTypeResult.FontSize = 20;
Label_MachineTypeResult.SetBinding(Label.ContentProperty, MachineBaseTypeBinding);
WrapPanel MachineTypeWrapPanel = new WrapPanel();
MachineTypeWrapPanel.Name = "MachineTypeWrapPanel";
MachineTypeWrapPanel.VerticalAlignment = System.Windows.VerticalAlignment.Top;
MachineTypeWrapPanel.Margin = new Thickness(2, 2, 2, 0);
MachineTypeWrapPanel.SetBinding(WrapPanel.BackgroundProperty, BgColorBinding);
MachineTypeWrapPanel.Children.Add(Label_MachineType);
MachineTypeWrapPanel.Children.Add(Label_MachineTypeResult);
My other bindings work fine, because I've just tied them to properties in code behind that implement property changed notification.
Trying to bind to any of the keys in my resources however, gives me nothing. The label's content is simply blank, and there are no errors in my debug output window.
I can't find any examples of anyone binding to their Properties.Resources.Whatever from code behind anywhere.
The solution:
Thanks Henka!
Binding GUI_MachineTypeBinding = new Binding("GUI_MachineType");
GUI_MachineTypeBinding.Source = Application.Current.FindResource("Resources");
....
Label_MachineType.SetBinding(Label.ContentProperty, GUI_MachineTypeBinding);
If you set the Binding from code behind the UI will not be notified you should create your custom extension and save a WeakReference to the DependencyProperty and update the value when the culture changed, i propose an other solution to use, have a look at this article.Advanced WPF Localization

How I can bind textblock with bolded and normal text

I have a part of text which some of the words are formatted.
These text are listed in a ListBox. When user clicks ListBoxitem, I want to collect that selectedItem and take user to the other place. My problem is that I cant bind TextBlock with another instance of TextBlock. And that TextBlock has many inlines, which I want to show.
I have been trying this solution:
<ListBox Width="800" Name="foundedTextBlocksListBox" SelectionChanged="foundedTextBlocksListBox_SelectionChanged" Background="Transparent" ItemsSource="{Binding}" Grid.Row="2" Visibility="Visible" Height="Auto" HorizontalAlignment="Center">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel VerticalAlignment="Center" Orientation="Vertical">
<TextBlock x:Name="foundedTextBlocks" DataContext="{Binding Textblock}"></TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
After Binding to DataContext like this:
ObservableCollection<FoundedTextBlock> listOfFoundedTextBlockResults = new ObservableCollection<FoundedTextBlock>();
TextBlock textblock = new TextBlock();
while (blockString.IndexOf("<b>") != -1)
{
int startOfWord = blockString.IndexOf("<b>");
int endOfWord = blockString.IndexOf("</b>");
string text = blockString.Substring(0, startOfWord);
textblock.Inlines.Add(text);
string boldedWord = blockString.Substring(startOfWord + 3, endOfWord - startOfWord - 3);
textblock.Inlines.Add(new Run() { Text = boldedWord, FontWeight = FontWeights.Bold });
blockString = blockString.Substring(endOfWord + 4);
textblock.Inlines.Add(blockString);
}
textblock.Tag = dbInfo;
listOfFoundedTextBlockResults.Add(new FoundedTextBlock() { Textblock = textblock });
}
foundedTextBlocksListBox.DataContext = listOfFoundedTextBlockResults;
I can't see any ListBoxItems in ListBox. Is my Binding wrong or is this possible at all?
I managed before to get TextBlock.Text property to show but not the Inlines where are bolded text or any other Inlines after my first inline addition to TextBlock.
How I can solve this annoiyng problem? In short, I need to display many TextBlocks with formatted text...
FoundedTextBlock class has TextBlock textblock {get;set;} property
I'm saving to Tag property my class instance, so I could collect the information I need when SelectedValueChanged event occurs.
Maybe you should use a ContentPresenter instead of TextBlock in your XAML
Replace
<TextBlock x:Name="foundedTextBlocks" DataContext="{Binding Textblock}"></TextBlock>
with
<ContentPresenter Content="{Binding Textblock}" />
Please try it out ... the rest of your code is missing to provide a better answer.

Remove elements from stackpanel

I have a button, when pressed it adds a textbox and a listbox to a stackpanel and adds this stackpanel to another stackpanel named "stackPanelAdd". Just like this:
private void buttonAdd_Click(object sender, RoutedEventArgs e)
{
StackPanel sp = new StackPanel();
TextBox tb = new TextBox();
ListBox lb = new ListBox();
tb.Margin = new Thickness(5, 5, 5, 0);
lb.Margin = new Thickness(5, 5, 5, 0);
lb.Height = 200;
sp.Children.Add(tb);
sp.Children.Add(lb);
stackPanelAdd.Children.Add(sp);
}
How do I remove the last children in the stackpanel "stackPanelAdd"?
Should I use something like stackPanelAdd.children.Remove? if so then how do i get the last element in the stackpanel?
Try:
if (stackPanelAdd.Children.Count>0)
{
stackPanelAdd.Children.RemoveAt(stackPanelAdd.Children.Count-1);
}
That is not a good idea, if you stick to this method things will probably get very messy sooner or later. When dealing with items that can be added and removed in WPF you will want to use an ItemsControl of some kind on top of panels (you can change the panel using the ItemsPanel property, by default it will be a StackPanel).
The creation of the controls can also be improved by using data templates and data binding which are core mechanisms that you should become familiar with.
An example:
<ItemsControl ItemsSource="{Binding Data}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBox Text="{Binding Name}" Margin="5,5,5,0"/>
<ListBox ItemsSource="{Binding Items}" Margin="5,5,5,0" Height="200"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Here Data is a source collection which should implement INotifyCollectionChanged, then you can just remove an item from that collection and its corresponding StackPanel will be gone. The items in Data should contain the bound properties Name and Items which you then can assign values to or get entered text from (the class should implement INPC, read more about those things in the article on data binding).
You can use
var lastControl = stackPanelAdd.Children.LastOrDefault();
//Last is defined in System.Linq.Enumrable
if(lastControl != null)
stackPanelAdd.Children.Remove(lastControl);
#Milan Halada's answer worked for me with a little change,
while (stackPanelAdd.Children.Count>0)
{
stackPanelAdd.Children.RemoveAt(stackPanelAdd.Children.Count-1);
}
so, it removes all the children and then i add new children to it dynamically using for loop, with new data.

Categories

Resources