Change main window implementation to user control - c#

I need to replace the following code usercontrol instead of main window (of course the main window is just calling to the userControl),while doing that I have the following problem.
Currently I tried to add the following code like in the main window in the
constructor of the usercontrol after the
public partial class UserControl: UserControl
{
private static MappingViewModelView _modelViewInstance;
public UserControl()
{
InitializeComponent();
_modelViewInstance = new MappingViewModelView();
DataContext = _modelViewInstance;
var source = Resources["source"] as CollectionViewSource;
if (source != null)
source.Source = _modelViewInstance.UserList;
ListBox.SelectionChanged += listbox_SelectionChanged;
But now in the user control there is no event SelectionChanged for list box (using the intlisense) just ListBox.SelectionChangedEvent which is not fit the original solution from the main window which is
ListBox.SelectionChanged += listbox_SelectionChanged;
error which is given if i put the exact code is: Cannot access non-static event 'SelectionChanged' in static context
Any idea why the list box behave different in the user control?
public partial class MainWindow : Window
{
public ObservableCollection<User> _UsersList = new ObservableCollection<User>();
private readonly Dictionary<string, string> _mapping = new Dictionary<string, string>();
private const string DRAG_SOURCE = "DragSource";
public MainWindow()
{
InitializeComponent();
_UsersList.Add(new User { Name = "Jhon" });
_UsersList.Add(new User { Name = "Mike" });
_UsersList.Add(new User { Name = "Alex" });
_UsersList.Add(new User { Name = "Darl" });
CollectionViewSource source = this.Resources["source"] as CollectionViewSource;
source.Source = _UsersList;
ListBox.SelectionChanged += listbox_SelectionChanged;
DataObject.AddCopyingHandler(text1, DragCopy);
DataObject.AddCopyingHandler(text2, DragCopy);
}
public ObservableCollection<User> UserList
{
get { return _UsersList; }
}
private void listbox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (e.AddedItems.Count == 1)
{
if (ListBox.SelectedItems.Count > 0)
{
var mySelectedItem = ListBox.SelectedItem as User;
if (mySelectedItem != null)
{
DragDrop.DoDragDrop(ListBox, mySelectedItem,
DragDropEffects.Copy | DragDropEffects.Move);
}
}
}
}
private void DropText_PreviewDragEnter(object sender, DragEventArgs e)
{
e.Effects = DragDropEffects.None;
}
private void DropText_PreviewDrop(object sender, DragEventArgs e)
{
var textbox = (TextBox)sender;
if (!(textbox.Text.Length > 0))
{
DataObject data = e.Data as DataObject;
User user = data.GetData(typeof(User)) as User;
textbox.Tag = user;
var name = user.Name;
textbox.Text += name;
textbox.Focus();
textbox.CaretIndex = textbox.Text.Length;
e.Handled = true;
var remove = _UsersList.Remove((User)ListBox.SelectedItem);
if (!_mapping.ContainsKey(textbox.Name))
_mapping.Add(textbox.Name, name);
}
e.Handled = true;
}
private void DropText_PreviewDragOver(object sender, DragEventArgs e)
{
e.Handled = true;
}
private void ListBox_Drop(object sender, DragEventArgs e)
{
DataObject data = e.Data as DataObject;
if (data != null)
{
User user = data.GetData(typeof(User)) as User;
if (user != null && !_UsersList.Contains(user))
_UsersList.Add(user);
}
TextBox txtBox = e.Data.GetData(DRAG_SOURCE) as TextBox;
if (txtBox != null)
{
if (_mapping.ContainsKey(txtBox.Name))
_mapping.Remove(txtBox.Name);
txtBox.Dispatcher.BeginInvoke((Action)(() => { txtBox.Text = string.Empty; }), System.Windows.Threading.DispatcherPriority.Normal);
}
e.Handled = true;
}
private void DragCopy(object sender, DataObjectCopyingEventArgs e)
{
if (e.IsDragDrop)
{
e.CancelCommand();
TextBox txtBox = sender as TextBox;
if (txtBox != null && txtBox.Tag != null)
{
DataObject dataObject = new DataObject(txtBox.Tag);
dataObject.SetData(DRAG_SOURCE, txtBox);
DragDrop.DoDragDrop(sender as DependencyObject, dataObject, DragDropEffects.Move | DragDropEffects.Copy);
}
e.Handled = true;
}
}
private void DropText_TextChanged(object sender, TextChangedEventArgs e)
{
TextBox txtBox = sender as TextBox;
if (txtBox.Text == string.Empty)
{
User user = txtBox.Tag as User;
if(user != null && !_UsersList.Contains(user))
_UsersList.Add(user);
if (_mapping.ContainsKey(txtBox.Name))
_mapping.Remove(txtBox.Name);
}
}
}
ListBox x:Name="ListBox" HorizontalAlignment="Left" Height="115"
VerticalAlignment="Top" Width="150" ItemsSource="{Binding Source={StaticResource source}}"
DisplayMemberPath="Name"
AllowDrop="True" Drop="ListBox_Drop" />
<Window.Resources>
<CollectionViewSource x:Key="source">
</CollectionViewSource>
</Window.Resources>
<TextBox x:Name="text1"
AcceptsReturn="True"
AllowDrop="True"
PreviewDragEnter="DropText_PreviewDragEnter"
PreviewDrop="DropText_PreviewDrop"
PreviewDragOver="DropText_PreviewDragOver"
TextChanged="DropText_TextChanged"
Grid.Column="1"
HorizontalAlignment="Left" Height="23" TextWrapping="Wrap"
VerticalAlignment="Top" Width="120"/>
<TextBox x:Name="text2"
AcceptsReturn="True"
AllowDrop="True"
PreviewDragEnter="DropText_PreviewDragEnter"
PreviewDrop="DropText_PreviewDrop"
PreviewDragOver="DropText_PreviewDragOver"
TextChanged="DropText_TextChanged"
Grid.Column="1"
HorizontalAlignment="Left" Height="23" TextWrapping="Wrap"
VerticalAlignment="Top" Width="120"/>

If you moved the ListBox to the UserControl, the most likely reasen is that - maybe by accident - the name was changed in the process.
The error message points in this direction as it recognizes ListBox as the type and not as the name of a concrete instance of a ListBox on the UserControl.

Related

UWP AdvancedCollectionView filter not working with strings

I have a AdvancedCollectionView from Windows Community Toolkit version 6.1.1 and trying to use it to filter out on 2 string properties.
I have created a simple app to reproduce the issue : https://github.com/touseefbsb/UWP-Filter-List
It has a textbox for filtering between StartNumber and EndNumber properties of items.
but as soon as I enter text "123" into it, it shows no item in the ListView when it should actually show only the first item, based on the test logic.
Code
MainPage.xaml
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<TextBox
x:Name="SearchTicketBooksBox"
Width="300"
Header="Search"
TextChanged="SearchTicketBooks_TextChanged" />
<ListView
x:Name="TicketBooksListView"
Grid.Row="1"
Margin="4,0,0,0"
ItemsSource="{x:Bind ViewModel.TicketBooks}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="app1:TicketBookDto">
<StackPanel Margin="20">
<TextBlock Text="{x:Bind StartNumber}" />
<TextBlock Text="{x:Bind EndNumber}" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
MainPage.xaml.cs
public sealed partial class MainPage : Page
{
public MainViewModel ViewModel { get; }
public MainPage() { InitializeComponent(); ViewModel = new MainViewModel(); }
private void SearchTicketBooks_TextChanged(object sender, TextChangedEventArgs e)
{
if (ViewModel != null)
{
if (string.IsNullOrWhiteSpace(SearchTicketBooksBox.Text))
{
ViewModel.TicketBooks.Filter = _ => true;
}
else
{
ViewModel.TicketBooks.Filter = x => ((TicketBookDto)x).StartNumber == SearchTicketBooksBox.Text;
//{
// var startNumber = Convert.ToInt32(((TicketBookDto)x).StartNumber);
// var endNumber = Convert.ToInt32(((TicketBookDto)x).EndNumber);
// var searchText = Convert.ToInt32(SearchTicketBooksBox.Text);
// return searchText >= startNumber && searchText <= endNumber;
//};
}
}
}
private void Page_Loaded(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
ViewModel.TicketBooks.Add(new TicketBookDto { StartNumber = "123", EndNumber = "456" });
ViewModel.TicketBooks.Add(new TicketBookDto { StartNumber = "789", EndNumber = "987" });
}
}
MainViewModel
public class MainViewModel : INotifyPropertyChanged
{
private readonly ObservableCollection<TicketBookDto> _ticketBooksPrivate = new ObservableCollection<TicketBookDto>();
private AdvancedCollectionView ticketBooks;
public AdvancedCollectionView TicketBooks
{
get
{
if (ticketBooks is null)
{
ticketBooks = new AdvancedCollectionView(_ticketBooksPrivate, true);
ticketBooks.ObserveFilterProperty(nameof(TicketBookDto.StartNumber));
ticketBooks.ObserveFilterProperty(nameof(TicketBookDto.EndNumber));
}
return ticketBooks;
}
set => Set(ref ticketBooks, value);
}
#region INotifyStuff
public event PropertyChangedEventHandler PropertyChanged;
protected void Set<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
{
if (Equals(storage, value))
{
return;
}
storage = value;
OnPropertyChanged(propertyName);
}
protected void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
#endregion
}
TicketBookDto
public partial class TicketBookDto
{
public string StartNumber { get; set; }
public string EndNumber { get; set; }
}
I have commented out code of the actual logic I need in the filter, which is to show the list items only those who have the search number between their "StartNumber" and "EndNumber" properties. But for simplicity I am using a simple match to StartNumber logic to find out why it aint working. Also when I add a boolean property and simply filter using that property then it works fine, its just not working with these string properties.
I'm afraid you can't use Filter in TextChanged event, please refer the source code here.
if (_filter != null)
{
for (var index = 0; index < _view.Count; index++)
{
var item = _view.ElementAt(index);
if (_filter(item))
{
continue;
}
RemoveFromView(index, item);
index--;
}
}
When you input text in the SerchBox and if the text is not equal to the filter property, the item will be RemoveFromView. So it will make the next input not effect. For this design, we suggest you make submit button to filter the data after finished input.
And If you do want to filter in the TextChanged, you could call ViewModel.TicketBooks.Filter = _ => true; to reset the viewtiems before set Filter delegate method like the following.
private void SearchTicketBooks_TextChanged(object sender, TextChangedEventArgs e)
{
if (ViewModel != null)
{
if (string.IsNullOrWhiteSpace(SearchTicketBooksBox.Text))
{
ViewModel.TicketBooks.Filter = _ => true;
}
else
{ // reset the filter
ViewModel.TicketBooks.Filter = _ => true;
ViewModel.TicketBooks.Filter = x => ((TicketBookDto)x).EndNumber == SearchTicketBooksBox.Text;
}
}
}

assign click event to a Button in a DataTemplate

<Window x:Class="WpfApp12.MainWindow"
xmlns=...usual namespaces...
Loaded="Window_Loaded"
>
<Window.Resources>
<DataTemplate x:Key="myHeaderTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{TemplateBinding Content}"/>
<Button Margin="5,0,0,0" x:Name="MyButton">Press me</Button>
</StackPanel>
</DataTemplate>
</Window.Resources>
<!-- Just point the datacontext to the code behind -->
<Window.DataContext>
<Binding RelativeSource="{RelativeSource Mode=Self}"/>
</Window.DataContext>
<DataGrid Name="DG" ItemsSource="{Binding People}"/>
</Window>
This, togheter with the code behind below gives just what I want: a DataGrid with a column whose header has been dynamically assigned a DataTemplate with a Button "Press me":
The code behind:
public partial class MainWindow : Window
{
public class Person
{
public string Name { get; set; }
public string Surname { get; set; }
}
public MainWindow()
{
People.Add(new Person() { Name = "Isaac", Surname = "Newton" });
People.Add(new Person() { Name = "Galileo", Surname = "Galilei" });
InitializeComponent();
}
public ObservableCollection<Person> People { get; } = new ObservableCollection<Person>();
private void Window_Loaded(object sender, RoutedEventArgs e)
{
DG.Columns[0].HeaderTemplate = (DataTemplate)FindResource("myHeaderTemplate");
//how to access the button in the template in order to assign the click event?
}
private void MyButton_Click(object sender, RoutedEventArgs e)
{
//DO SOMETHING
}
}
}
Now i want to dynamically wire MyButton_Click event to the button in the template.
This kind of problems seem to have a lot of coverage, this one being one of the best:
WPF How to access control from DataTemplate
There there is something like:
ComboBox myCombo = _contentPresenter.ContentTemplate.FindName("myCombo", _contentPresenter) as ComboBox;
I'm not very familiar with the templating, and I cannot find the starting point, the "content presenter" on which to call the FindName.
You could use a recursive helper method that finds the Button in the visual tree:
private void Window_Loaded(object sender, RoutedEventArgs e)
{
DG.Columns[0].HeaderTemplate = (DataTemplate)FindResource("myHeaderTemplate");
DG.Dispatcher.BeginInvoke(new Action(() =>
{
DataGridColumnHeadersPresenter presenter = FindVisualChild<DataGridColumnHeadersPresenter>(DG);
DataGridCellsPanel dataGridCellsPanel = FindVisualChild<DataGridCellsPanel>(presenter);
DataGridColumnHeader header = dataGridCellsPanel.Children[0] as DataGridColumnHeader;
Button button = FindVisualChild<Button>(header);
if (button != null)
button.Click += MyButton_Click;
}));
}
private void MyButton_Click(object sender, RoutedEventArgs e)
{
//DO SOMETHING
}
private static T FindVisualChild<T>(DependencyObject obj) where T : DependencyObject
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(obj, i);
if (child != null && child is T)
return (T)child;
else
{
T childOfChild = FindVisualChild<T>(child);
if (childOfChild != null)
return childOfChild;
}
}
return null;
}

Crash when trying to apply drag drop reorder to a ItemsControl

I am trying to apply drag drop to a dynamically created collection of buttons on a ItemsControl. I get an error:
Cannot explicitly modify Children collection of Panel used as ItemsPanel for ItemsControl. ItemsControl generates child elements for Panel.
I am not sure how I can fix this.
My xaml:
<ItemsControl Grid.Row="2" Grid.Column="0" IsTabStop="False" Name="icsp"
ItemsSource="{Binding Path=ContentButtons}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel x:Name="sp" AllowDrop="True" Background="SkyBlue"
PreviewMouseLeftButtonDown="sp_PreviewMouseLeftButtonDown"
PreviewMouseLeftButtonUp="sp_PreviewMouseLeftButtonUp"
PreviewMouseMove="sp_PreviewMouseMove"
DragEnter="sp_DragEnter" Drop="sp_Drop"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
My code behind:
public partial class Admin : UserControl
{
public Admin()
{
InitializeComponent();
}
private bool _isDown;
private bool _isDragging;
private Point _startPoint;
private UIElement _realDragSource;
private UIElement _dummyDragSource = new UIElement();
private void sp_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var sp = FindChild<StackPanel>(Application.Current.MainWindow, "sp");
if (e.Source == sp)
{
}
else
{
_isDown = true;
_startPoint = e.GetPosition(sp);
}
}
private void sp_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
_isDown = false;
_isDragging = false;
_realDragSource.ReleaseMouseCapture();
}
private void sp_PreviewMouseMove(object sender, MouseEventArgs e)
{
if (_isDown)
{
var sp = FindChild<StackPanel>(Application.Current.MainWindow, "sp");
if ((_isDragging == false) &&
((Math.Abs(e.GetPosition(sp).X - _startPoint.X) > SystemParameters.MinimumHorizontalDragDistance) ||
(Math.Abs(e.GetPosition(sp).Y - _startPoint.Y) > SystemParameters.MinimumVerticalDragDistance)))
{
_isDragging = true;
_realDragSource = e.Source as UIElement;
_realDragSource.CaptureMouse();
DragDrop.DoDragDrop(_dummyDragSource, new DataObject("UIElement", e.Source, true),
DragDropEffects.Move);
}
}
}
private void sp_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent("UIElement"))
{
e.Effects = DragDropEffects.Move;
}
}
private void sp_Drop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent("UIElement"))
{
var sp = FindChild<StackPanel>(Application.Current.MainWindow, "sp");
UIElement droptarget = e.Source as UIElement;
int droptargetIndex =-1, i =0;
foreach (UIElement element in sp.Children)
{
if (element.Equals(droptarget))
{
droptargetIndex = i;
break;
}
i++;
}
if (droptargetIndex != -1)
{
sp.Children.Remove(_realDragSource);
sp.Children.Insert(droptargetIndex, _realDragSource);
}
_isDown = false;
_isDragging = false;
_realDragSource.ReleaseMouseCapture();
}
}
Find child is a method used to search the visual tree and grab the panel named sp. It works and returns the control. When I apply this code to a stack panel with buttons created in xaml everything works. It is just when I try to use it in an ItemsControl that it blows up.

Universally usable editable label

I'm implementing a way to rename elements in a treeview. My thought was not to build a special TreeView, but instead a special Label which can also be used in ListBox and other controls. It sets the focus to itself by clicking it, so I changed Focusable to true. If focused it gets editable by [F2] and when it gets clicked while already having focus. Editable means, a text box shows (all similar to Windows Explorer). Unfortunately the TreeViewItem does not get selected, when I click the label. When clicking the Icon to the left, the TreeViewItem is selected.
I do not handle any event setting Handled=true, but I think the Label itself handles the click, so the treeviewItem does not get the opportunity to react to it. If I am right here, is there a way to modify the label (own class?) in a way it does not handle the event at all?
I rethought my attempt. The solution is not to take the focus at all. Instead I bound a handler to the KeyUp event of the observed element currently having the focus (see the comment in EditableLabel.cs).
EditableLabel.xaml:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:myown.Wpf"
xmlns:localCtrls="clr-namespace:myown.Wpf.Controls">
<Style TargetType="{x:Type localCtrls:EditableLabel}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type localCtrls:EditableLabel}">
<StackPanel>
<Label x:Name="label"
Content="{TemplateBinding Text}"
Visibility="Visible"
Height="{TemplateBinding Height}"
Width="{TemplateBinding Width}"
Padding="{TemplateBinding Padding}"
Foreground="{TemplateBinding Foreground}"/>
<!-- TemplateBinding is always OneWay! -->
<TextBox x:Name="textbox"
Text="{Binding Path=Text, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"
Visibility="Collapsed"
Height="{TemplateBinding Height}"
Width="{TemplateBinding Width}"
Padding="{TemplateBinding Padding}"/>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
EditableLabel.cs:
public partial class EditableLabel : Label
{
#region DependencyProperties
public static readonly DependencyProperty IsEditingProperty =
DependencyProperty.Register("IsEditing", typeof(bool), typeof(EditableLabel),
new UIPropertyMetadata(false, IsEditingUpdate));
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(string), typeof(EditableLabel),
new FrameworkPropertyMetadata("",
FrameworkPropertyMetadataOptions.AffectsRender |
FrameworkPropertyMetadataOptions.AffectsParentMeasure |
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public bool IsEditing
{
get { return (bool)GetValue(IsEditingProperty); }
set { SetValue(IsEditingProperty, value); }
}
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
private string m_lastValue = "";
private IInputElement m_lastFocus = null;
private Label m_label = null;
private TextBox m_textBox = null;
#endregion
static EditableLabel()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(EditableLabel),
new FrameworkPropertyMetadata(typeof(EditableLabel)));
}
public EditableLabel()
{
LostFocus += (s, e) => { };
LostKeyboardFocus += EditableLabel_LostKeyboardFocus;
}
private void EditableLabel_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
if (e.NewFocus != null)
Debug.WriteLine(e.NewFocus.GetType().Name);
}
public override void OnApplyTemplate()
{
m_label = GetTemplateChild("label") as Label;
m_textBox = GetTemplateChild("textbox") as TextBox;
m_label.MouseUp += Label_MouseUp;
m_textBox.LostFocus += (s, e) => IsEditing = false;
m_textBox.KeyUp += (s, e) => { TextBox_KeyUp(s, e); e.Handled = true; };
m_textBox.GotKeyboardFocus += (s, e) => m_textBox.SelectAll();
base.OnApplyTemplate();
}
private void Label_MouseUp(object sender, MouseButtonEventArgs e)
{
DependencyObject scope = FocusManager.GetFocusScope(this);
IInputElement currFocus = FocusManager.GetFocusedElement(scope);
if ((currFocus != null))
{
if (currFocus == m_lastFocus)
{
IsEditing = true;
}
else
{
m_lastFocus = currFocus;
DependencyObject observedObject = currFocus as DependencyObject;
if (observedObject != null)
{
m_lastFocus.LostKeyboardFocus += ObservedElementLostFocus;
m_lastFocus.KeyUp += ObservedElement_KeyUp; // THIS IS THE TRICK
}
}
}
}
private void ObservedElement_KeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.F2)
{
IsEditing = true;
e.Handled = true;
}
}
private void ObservedElementLostFocus(object sender, RoutedEventArgs e)
{
KeyboardFocusChangedEventArgs kfc = e as KeyboardFocusChangedEventArgs;
if (kfc.NewFocus != null)
{
if ((kfc.NewFocus != m_textBox) && (kfc.NewFocus != m_lastFocus))
{
m_lastFocus.LostKeyboardFocus -= ObservedElementLostFocus;
m_lastFocus.KeyUp -= ObservedElement_KeyUp;
m_lastFocus = null;
}
}
}
private void TextBox_KeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.Escape)
{
IsEditing = false;
Text = m_lastValue;
}
else if (e.Key == Key.Enter)
{
IsEditing = false;
}
}
private static void IsEditingUpdate(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
EditableLabel self = obj as EditableLabel;
if ((bool)e.NewValue)
{
self.m_lastValue = self.Text;
self.m_textBox.Visibility = Visibility.Visible;
self.m_textBox.Focus();
self.m_label.Visibility = Visibility.Collapsed;
}
else
{
self.m_textBox.Visibility = Visibility.Collapsed;
self.m_label.Visibility = Visibility.Visible;
if (self.m_lastFocus != null)
self.m_lastFocus.Focus();
}
}
}

How to get lable name in dynamically?

<Grid x:Name="LayoutRoot">
<TextBox x:Name="txt_diplay_1" HorizontalAlignment="Left" Height="42" Margin="155,78,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="103.5" GotFocus="txt_diplay_1_GotFocus" />
<TextBox x:Name="txt_diplay_2" Height="42" Margin="297,78,239.5,0" TextWrapping="Wrap" VerticalAlignment="Top" GotFocus="txt_diplay_2_GotFocus" />
<Button x:Name="btn_a" Content="A" HorizontalAlignment="Left" Height="40" Margin="155,147,0,0" VerticalAlignment="Top" Width="73" Click="btn_a_Click" />
<Button x:Name="btn_b" Content="B" Height="40" Margin="237,147,0,0" VerticalAlignment="Top" Click="btn_b_Click" HorizontalAlignment="Left" Width="73" />
<Button x:Name="btn_c" Height="40" Margin="0,147,239.5,0" VerticalAlignment="Top" HorizontalAlignment="Right" Width="73" Click="btn_c_Click" >
<Grid Height="30.833" Width="61.5">
<Label x:Name="lbl_1" Content="1" Margin="22.498,6.5,19.501,2.166"/>
<Label x:Name="lbl_2" Content="!" HorizontalAlignment="Right" Margin="0,-4.422,0,13.088" Width="19.501"/>
</Grid>
</Button>
</Grid>
The design will be like this
public partial class MainWindow : Window
{
Control TexboxDetails = null;
Control ButtonDetails;
Button BehaveButton;
public MainWindow()
{
this.InitializeComponent();
}
private void btn_a_Click(object sender, RoutedEventArgs e)
{
ButtonDetails = (Control)sender;
all_in_one();
}
private void btn_b_Click(object sender, RoutedEventArgs e)
{
ButtonDetails = (Control)sender;
all_in_one();
}
private void btn_c_Click(object sender, RoutedEventArgs e)
{
}
private void txt_diplay_1_GotFocus(object sender, RoutedEventArgs e)
{
TexboxDetails = (Control)sender;
}
private void txt_diplay_2_GotFocus(object sender, RoutedEventArgs e)
{
TexboxDetails = (Control)sender;
}
public void all_in_one()
{
BehaveButton = ButtonDetails as Button;
if (TexboxDetails != null)
{
TextBox BehaveTextbox = TexboxDetails as TextBox;
var caret_index = BehaveTextbox.CaretIndex;
BehaveTextbox.Text = BehaveTextbox.Text.Insert(caret_index, BehaveButton.Content.ToString());
BehaveTextbox.Focus();
BehaveTextbox.CaretIndex = caret_index + 1;
}
}
}
With above code i can get Button name dynamically when i click that button.
In above figure one button(btn_c) has two labels. now i want get that separate labels name dynamcially when i click button(btn_c).
You can get them like this (inside the btn_c click handler):
var btn_c = (Button)sender;
Grid grid = (Grid)btn_c.Content;
Label label1 = (Label)grid.Children[0];
string name1 = label1.Name;
Your whole design could really use some rework. Take a look at this code: (notice the reduced number of event handlers; you'll need to modify the XAML to use these)
public partial class MainWindow : Window
{
TextBox LastFocusedTextBox;
public MainWindow()
{
this.InitializeComponent();
}
private void btn_Click(object sender, RoutedEventArgs e)
{
InsertButtonContent((Button)sender);
}
private void txt_diplay_GotFocus(object sender, RoutedEventArgs e)
{
LastFocusedTextBox = (TextBox)sender;
}
public void InsertButtonContent(Button button)
{
if (LastFocusedTextBox != null)
{
string buttonContentString = button.Content as string;
if (string.IsNullOrEmpty(buttonContentString))
{
var grid = button.Content as Grid;
if (grid != null)
buttonContentString = string.Join("", grid.Children.OfType<ContentControl>().Select(x => x.Content));
}
var caret_index = LastFocusedTextBox.CaretIndex;
LastFocusedTextBox.Text = LastFocusedTextBox.Text.Insert(caret_index, buttonContentString);
LastFocusedTextBox.Focus();
LastFocusedTextBox.CaretIndex = caret_index + buttonContentString.Length;
}
}
}
Notice how the Button are passed to the method instead of being stored in a field. Also, unnecessary fields, both in the class and local to the all_in_one() method were removed. To get the contents of the labels in the Grid (e.g. "1!" - I assume this is what you were after, since nothing else could go into a simple string field, and also match the general pattern of your first two buttons), we simply select their contents and join them into a single string, after checking if the content was a string or a Grid.

Categories

Resources