In my item template in longlistselector I have a hyperlink button.
When I'm clicking on button, that item should be deleted.
The problem is that if there is no selected item, I need to click twice on button, because after first click SelectedItem in LonglistSelector is null.
How to fix it, that click on button will automatically set selection on list to button's parent?
You can do this in two different ways (ignoring MVVM pattern). You can delete the item in the Click eventhandler of the HyperLinkButton or you can set the SelectedItem of the LongListSelector, so you can delete it right after.
public ObservableCollection<object> List { get; set; }
public MainPage()
{
InitializeComponent();
List = new ObservableCollection<object>() { "aaaa", "bbb", "cccc", "dddd", "eeee"};
LongList.ItemsSource = List;
}
private void HyperlinkButton_Click(object sender, RoutedEventArgs e)
{
var hyperLinkButton = sender as HyperlinkButton;
var boundItemDataContext = hyperLinkButton.DataContext;
List.Remove(boundItemDataContext); // #1 Delete it directly from the list that automatically gets updated because it's an ObservableCollection.
LongList.SelectedItem = boundItemDataContext; // #2 Set the SelectedItem property to the current DataContext, so you can delete it in the SelectionChanged eventhandler.
}
private void LongList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var longListSelector = sender as LongListSelector;
List.Remove(longListSelector.SelectedItem);
}
Related
I have a ContextFlyout in my form and I want the listbox to select the index where the mouse is upon right-click
Originally I thought I could take advantage of the RightTapped event so I created an event handler, but while filling out the method, I didn't see any way to translate the position of the mouse to an item in the listbox.
RightTapped event
private void SideMenu_RightClick(object sender, RightTappedRoutedEventArgs e) {
ListBox menu = (ListBox)sender;
SideMenu.SelectedIndex = menu.IndexFromPoint(e.);
menu.
}
I've looked through all the methods and properties but I can't seem to find what I need. I found a lot of solutions for WPF, but this is UWP and those methods do not exist on these UWP objects
An easier approach would be to attach the event handler to the ListBoxItem or the root element in the ItemTemplate. You'll find an example of how you could do this here.
I figured out how to do it. Firstly, both my MenuFlyout and items for the listbox are generated programmatically.
Creating MenuFlyout
//this is a property in the class
internal MenuFlyout rightclick = new MenuFlyout();
//In Page's Constructor
this.InitializeComponent();
MenuFlyoutItem mfi = new MenuFlyoutItem();
mfi.Text = "Copy";
rightclick.Items.Add(mfi);
mfi = new MenuFlyoutItem();
mfi.Text = "Delete";
rightclick.Items.Add(mfi);
rightclick.Opened += rightclick_opened; //run method when flyout is opened
Method for the Opened event
private void rightclick_opened(object sender, object e) {
MenuFlyout mf = (MenuFlyout)sender;
SideMenu.SelectedItem = mf.Target; //makes the magic happen
}
Instantiating ListBoxItems
private void NewLocation(object sender, RoutedEventArgs e) {
Location newLocation = new Location(); //custom class
ListBoxItem nl = new ListBoxItem(); //creates empty ListBoxItem
nl.Content = newLocation.objectName; //give listboxitem default name from the class constructor
nl.ContextFlyout = rightclick; //set contextflyout for item
SideMenu.Items.Add(nl); //add new item to listbox
locations.Add(newLocation); //add new object to "linked" list
SideMenu.SelectedIndex = locations.Count - 1; //set current selected to new item
}
I have a listview where each row has few images and some text blocks.
If I use ItemClick event for ListView, I can easily get the clicked item (binded object) using something like this:
private void MainListView_ItemClick(object sender, ItemClickEventArgs e)
{
var device = (Device)e.ClickedItem;
}
But I want to distinguish between clicks on different elements (images) within the ListView row. So I use Tapped event for ImageView (which is inside ListView) where event handler looks like this:
private void image_Tapped(object sender, TappedRoutedEventArgs e)
{
}
How can I get the clicked ListView item in this case?
You can get the item from the data context of the tapped element
var fe = sender as FrameworkElement;
var device = fe.DataContext as Device;
I have a listbox, with 2 buttons, new and delete. new adds an item into the list box, and the delete button should delete the item out of the list box. The list box items are tied to a class that stores user entered data from text boxes below.
private void AddListBox()
{
lstCondition.BeginUpdate();
Condition cond = new Condition("");
cond.Name = string.Format("Condition {0}", _selection.NetConditions.Count + 1);
_selection.NetConditions.Add(cond);
lstCondition.EndUpdate();
lstCondition.SelectedItem = cond;
cboNetCondition.Properties.Items.Clear();
cboNetCondition.Properties.Items.AddRange(NetCondition);
cboControlType.Properties.Items.Clear();
cboControlType.Properties.Items.AddRange(ControlType);
cboFlowRate.Properties.Items.Clear();
cboFlowRate.Properties.Items.AddRange(FlowRate);
}
private void btnNew_Click(object sender, EventArgs e)
{
AddListBox();
}
the cbo items are comboboxes, whose data gets tied in the condition class to each instance of the list box.
public frmNetConditions(Condition condo, Selection selection)
{
InitializeComponent();
_selection = selection;
lstCondition.DataSource = _selection.NetConditions;
condition = _selection.NetConditions.Count;
}
private void btnDelete_Click(object sender, EventArgs e)
{
selectedCondition = (Condition)lstCondition.SelectedItem;
cboControlType.SelectedIndex = -1;
cboNetCondition.SelectedIndex = -1;
cboFlowRate.SelectedIndex = -1;
txtFlowRate.Text = string.Empty;
txtStatPressure.Text = string.Empty;
txtDampOpening.Text = string.Empty;
txtDensity.Text = string.Empty;
cboDensity.SelectedIndex = -1;
lstCondition.Items.Remove(lstCondition.SelectedItem);
lstCondition.Refresh();
}
After pressing this delete button, the listbox, still contains the item i wish to delete, im unsure why thats the case?
Update with datasource
public List<Condition> NetConditions { get { return _netconditions; } }
As already suggested, you should bind to a BindingList<Condition> instead of a List<Condition>. This allows you to change the datasource and the control (ListBox) to get notified by your changes. The code should look like this:
lstCondition.ValueMember = "ConditionId";
lstCondition.DisplayMember = "Name";
lstCondition.DataSource = NetConditions;
After defining the binding, the correct way of operating on the ListBox items is to remove from the datasource, not the ListBox itself:
// SelectedItem should be checked for null (no selection is an option)
NetCondition.Remove((Condition)lstCondition.SelectedItem);
However, if you plan to change properties from an element (so, not the list itself), the control is notified only if your element (Condition) implements INotifyPropertyChanged interface.
I have two views of WPF (Vista1.xaml and Vista2.xaml), and they are part of a MainWindow.xaml.
In the Vista1.xaml i have a listview, where the user selects some items by clicking and the Vista2.xaml has a button.
I want that when the user clicks on the button of Vista2.xaml, get the items that the user previously selected in the listview of Vista1.xaml.
I have class in the Vista1.xaml.cs ListViewItem_PreviewMouseLeftButtonDown method that captures the user selects the item in the listview.
the code is as follows
private void ListViewItem_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var item = sender as ListViewItem;
if (item != null && item.IsSelected)
{
...
}
}
I appreciate your help
Add a public property to you MainPage that contains the data you want to pass between Vista1 and Vista2. Then, in your event handler of Vista1, set the property and on the button click of Vista2 read the property.
I subscribed to a SelectionChangedEvent on a ComboBox in a DataGrid with the following code:
public static DataGridTemplateColumn CreateComboboxColumn(string colName, Binding textBinding, SelectionChangedEventHandler selChangedHandler = null)
{
var cboColumn = new DataGridTemplateColumn {Header = colName};
...
if (selChangedHandler != null)
cboFactory.AddHandler(Selector.SelectionChangedEvent, selChangedHandler);
...
return cboColumn;
}
The handler I actually register contains:
private void ComboBoxSelectionChangedHandler(object sender, SelectionChangedEventArgs e)
{
Console.WriteLine(#"selectHandler");
var cboBox = sender as ComboBox;
if (cboBox == null)
return;
if (cboBox.IsDropDownOpen) // a selection in combobox was made
{
CommitEdit();
}
else // trigger the combobox to show its list
cboBox.IsDropDownOpen = true;
}
... and is located in my custom DataGrid class.
If I select an item in the ComboBox, e.AddedItems and cboBox.SelectedItem contains the selected value, but nothing is changed on CommitEdit().
What I want is to force a commit to directly update the DataGrid's ItemsSource, when the user selects an item in the drop-down-list. Normally this is raised if the control looses focus...
The link in the solution found in this thread is not available any more and I don't know how to use this code.
I created a tricky, but working, solution for my problem. Here's the modified handler from above:
private void ComboBoxSelectionChangedHandler(object sender, SelectionChangedEventArgs e)
{
Console.WriteLine(#"selectHandler");
var cboBox = sender as ComboBox;
if (cboBox == null)
return;
if (cboBox.IsDropDownOpen) // a selection in combobox was made
{
cboBox.Text = cboBox.SelectedValue as string;
cboBox.MoveFocus(new TraversalRequest(FocusNavigationDirection.Right));
}
else // user wants to open the combobox
cboBox.IsDropDownOpen = true;
}
Because my ComboBoxColumn is a custom DataGridTemplateColumn I force it to show its list, when the user first selects the cell.
To change the bound items value I manually overwrite the displayed text with recently selected item and force the UI to select another item (in this case the control to the right) to make an implicit call to CellEditEnding event, which (in my case) commits the whole row:
private bool _isManualEditCommit = false;
private void _CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
// commit a manual edit
// this if-clause prevents double execution of the EditEnding event
if (!_isManualEditCommit)
{
Console.WriteLine(#"_CellEditEnding() manualeditcommit");
_isManualEditCommit = true;
CommitEdit(DataGridEditingUnit.Row, true);
_isManualEditCommit = false;
checkRow(e.Row);
}
}
Maybe I could help somebody with this "dirty" solution ;-)