My aim is to be able to add/ edit/delete items to a listbox. I have created a listbox of textboxes in the following way. I am able to display data but I am not able to edit data. Can someone help me modify the code so that I can achieve this functionality.
<ListBox Name="lbDemoBox" ItemsSource="{Binding testList}" Grid.Column="0" Grid.Row="0" SelectionChanged="lbDemoBox_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBox Text="{Binding Path=.}" KeyDown="TextBox_KeyDown" KeyUp="TextBox_KeyUp" GotFocus="TextBox_GotFocus"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Here is the code behind
public partial class MainPage : UserControl
{
private string focusedString { get; set; }
public MainPage()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
LayoutRoot.DataContext = new ViewModel();
}
private void TextBox_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter && (Keyboard.Modifiers & (ModifierKeys.Shift)) == ModifierKeys.Shift)
{
(lbDemoBox.ItemsSource as ObservableCollection<string>).Add(string.Empty);
}
}
private void TextBox_KeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.Delete)
{
int index = (lbDemoBox.ItemsSource as ObservableCollection<string>).IndexOf(focusedString);
(lbDemoBox.ItemsSource as ObservableCollection<string>).RemoveAt(index);
}
}
private void TextBox_GotFocus(object sender, RoutedEventArgs e)
{
focusedString = (sender as TextBox).Text;
}
private void lbDemoBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
}
}
public class ViewModel
{
public ObservableCollection<string> testList
{
get { return new ObservableCollection<string> { "Item1", "Item2", "Item3" }; }
}
}
Try this:
<TextBox Text="{Binding Path=YourProperty, Mode=TwoWay}" />
Related
I am having issue that I've been struggling since I was programming apps in Xamarin. The problem is when I want change a label's text value outside from the ContentPage's Main method it does not update on the user interface.
public partial class MainPage : ContentPage
{
int command = 0;
SimpleTcpServer server1 = null;
SimpleTcpServer server2 = null;
System.Timers.Timer timer = null;
string iPPort = null;
public string Data { get; set; } = "getting data";
public MainPage()
{
InitializeComponent();
NetworkAccess accessType = Connectivity.Current.NetworkAccess;
if (accessType == NetworkAccess.Internet)
{
server1 = new SimpleTcpServer("10.0.0.9:10000");
server2 = new SimpleTcpServer("10.0.0.9:11000");
timer = new System.Timers.Timer(150);
timer.Elapsed += Tick;
timer.AutoReset = true;
server1.Events.ClientConnected += ClientConnected;
server1.Events.ClientDisconnected += ClientDisconnected;
server2.Events.ClientConnected += ClientConnected2;
server2.Events.ClientDisconnected += ClientDisconnected2;
server2.Events.DataReceived += DataReceived2;
label.Text = Data;
server1.Start();
server2.Start();
}
}
public void DataReceived2(object sender, SuperSimpleTcp.DataReceivedEventArgs e)
{
ArraySegment<byte> buffer = e.Data;
Data = Encoding.Default.GetString(buffer);
label.Text = Data;
}
private void ClientDisconnected2(object sender, ConnectionEventArgs e)
{
throw new NotImplementedException();
}
private void ClientConnected2(object sender, ConnectionEventArgs e)
{
}
private void Tick(object sender, ElapsedEventArgs e)
{
server1.Send(iPPort, command.ToString());
}
private void ClientDisconnected(object sender, ConnectionEventArgs e)
{
throw new NotImplementedException();
}
private void ClientConnected(object sender, ConnectionEventArgs e)
{
iPPort = e.IpPort;
timer.Start();
}
private void Forward(object sender, EventArgs e)
{
command = 1;
}
private void Backward(object sender, EventArgs e)
{
command = 2;
}
private void Left(object sender, EventArgs e)
{
command = 3;
}
private void Right(object sender, EventArgs e)
{
command = 4;
}
private void Released(object sender, EventArgs e)
{
command = 0;
}
}
This is my .NET Maui C# program which basically creates two Tcp listeners, which listen to two ports-one for sending and one for receiving (It is important to be on two different ports because of the second part of the project). When a data is received from the second port (the receiving port) a method DataReceived2 is raised and it gets the data and changes the label text value with it. When I debug the program I see that the value of label is changed with what it should be but it does not change on the ContentPage. I tried Data biding too, but the result is the same.
<StackLayout>
<Grid x:Name="grid">
<StackLayout VerticalOptions="CenterAndExpand" Margin="10,290,0,0">
<StackLayout Orientation="Horizontal">
<StackLayout Margin="0,120,0,60">
<Button VerticalOptions="CenterAndExpand" BackgroundColor="Green" Pressed="Forward" Released="Released" CornerRadius="50" Margin="0,0,0,-20" HeightRequest="100" WidthRequest="100"></Button>
<Button HeightRequest="100" Pressed="Backward" BackgroundColor="Green" Released="Released" WidthRequest="100" CornerRadius="50"></Button>
</StackLayout>
<StackLayout Margin="20,200,0,120" Orientation="Horizontal">
<Button CornerRadius="100" Pressed="Left" BackgroundColor="Green" Released="Released" HeightRequest="100" WidthRequest="100"></Button>
<Button HeightRequest="100" Pressed="Right" BackgroundColor="Green" Released="Released" Margin="10,0,0,0" WidthRequest="100" CornerRadius="60"></Button>
</StackLayout>
</StackLayout>
</StackLayout>
<StackLayout x:Name="stack">
<Label x:Name="label" Text="" HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand"/>
</StackLayout>
</Grid>
</StackLayout>
And this is my xaml code.Can somebody help with this problem.
Thanks #Oliver, working for me:
in MAUI showing a progress label-text in webClient.DownloadAsync() like this:
XAML
<Label x:Name="progressBarText"
Text="..." />
C#
private void WebClient_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
try
{
progressBar.Progress = (double)(e.ProgressPercentage / 100.0);
Application.Current.MainPage.Dispatcher.Dispatch(() => progressBarText.Text = String.Format( "Downloading {0}%", e.ProgressPercentage ));
}
catch (Exception error)
{
throw error;
}
}
<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;
}
I have created two pages in the application ...
There on the front page Tkstpeix write your name when entering the storage and set up the application on this page,
And when you enter the second page in the application name does not come out!
Example:
When I open the app and type in my name "Ibra" the text box on the second page my name does not appear!
->Page1:
using myProject.Model;
public partial class Test1 : PhoneApplicationPage
{
IsolatedStorageSettings Data = IsolatedStorageSettings.ApplicationSettings;
List<UserData> ObjUserDataList = new List<UserData>();
public Test1()
{
InitializeComponent();
this.Loaded += Test1_Loaded;
}
private void Test1_Loaded(object sender, RoutedEventArgs e)
{
if (Data.Contains("UserNameData"))
{
NavigationService.Navigate(new Uri("/Test2.xaml", UriKind.Relative));
}
}
private void NameBox_GotFocus(object sender, RoutedEventArgs e)
{
TextBox tb = (TextBox)sender;
tb.BorderBrush = new SolidColorBrush(Colors.LightGray);
}
private void button_Click(object sender, RoutedEventArgs e)
{
Data["UserNameData"] = NameBox.Text;
NavigationService.Navigate(new Uri("/Test2.xaml", UriKind.Relative));
}
}
-->Page2:
using myProject.Model;
public partial class Test2 : PhoneApplicationPage
{
IsolatedStorageSettings Data = IsolatedStorageSettings.ApplicationSettings;
UserData ObjUserData = new UserData();
public Test2()
{
InitializeComponent();
this.Loaded += Test2_Loaded;
}
private void Test2_Loaded(object sender, RoutedEventArgs e)
{
if (Data.Contains("UserNameData"))
{
StckUserDetailsUI.DataContext = ObjUserData;
}
}
}
<StackPanel Name="StckUserDetailsUI" Grid.Row="0" Margin="12,17,0,28" Grid.ColumnSpan="2">
<TextBlock Text="Your Details :" Foreground="White" FontSize="30" TextDecorations="Underline"/>
<TextBlock FontSize="40" Name="TxtUserName" Text="{Binding UserName}" Foreground="White"/>
</StackPanel>
--->UserData.Cs: (in in the file /Model)
class UserData
{
public string UserName { get; set; }
}
note:
I work in windows phone 8.1 silverlight
You set the DataContext to ObjUserData but you never put anything for ObjUserData.UserName, hence it comes back as blank.
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.
<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.