I have a list of products, sitting in a ListView. Each product has details. If I press a button in one of the products within the ListView, the event handler is bound to the product and all its details. Lets say for arguments sake that the button fires the following event handler:
public async void OnClickViewImageCarousel(object sender, EventArgs e)
{
var selectedItemDetails = ((Button)sender).CommandParameter;
}
During debugging, the selectedItemDetails shows the following locals:
How do you access the fields? As in how could I do something like:
var FieldIWantToUse = selectedItemsDetails.ShortDescription
Thanks guys.
var FieldIWantToUse = ((RackProduct)selectedItemsDetails.selectedItems).ShortDescription;
Or
var FieldIWantToUse = selectedItemsDetails.selectedItems.ShortDescription;
Is it working?
You should use direct casting to the items type from which your listView consists of. A little example (for popup menu but the idea the same):
XAML:
<MenuItem ...Clicked="ButtonClicked" CommandParameter="{Binding .}" />
Code:
private void ButtonClicked(object sender, EventArgs args)
{
var yourVar = (YourType)((MenuItem)sender).CommandParameter;
...
}
Related
I am going to drag an item from a ListView to drop a box to process something.
In this case, I am not able to get selected ListView item. Selected Index/Items always returns -1/null.
Note: I am able to get selected listview item when using SelectionChanged.
But not able to get drop event. Please advise.
The XAML source:
<ListView x:Name="lvMaster" CanDragItems="True" SelectionChanged="lvMaster_SelectionChanged" />
<Grid AllowDrop="True" Drop="Drop_Event" DragOver="DragOver_Event">
</Grid>
The C# source:
private void Drop_Event(object sender, DragEventArgs e)
{
lvObj = new ListView();
ListView)sender;
}
private void DragOver_Event(object sender, DragEventArgs e)
{
AcceptedOperation = DataPackageOperation.Copy;
DragUIOverride.IsCaptionVisible = true;
DragUIOverride.IsContentVisible = true;
}
You can register DragItemsStarting event or DragItemsCompleted event for your listview, then in its handler method, you could get all items you dragged.
private void SourceListView_DragItemsCompleted(ListViewBase sender, DragItemsCompletedEventArgs args)
{
var cc = args.Items;
}
Please refer to the official Drag and Drop sample for more details.
Please
I'm having some trouble with Drag and Drop between different ListViews. I have a GridView that contains multiple ListView all from the same ObservableCollection. Basically, I want to be able to drag items from one ListView into another Listview but within the same GridView.
Below is the ListView Which is part of the DataTemplate for the GridView. The ListView is Bound to a ObservableCollection of string. Which is a Property or the ObservableCollection the GridView is bound too.
<ListView Name="ListingView" Height="200" HorizontalAlignment="Center" Grid.Row="1" CanDragItems="True" AllowDrop="True"
DragItemsStarting="ListView_DragItemsStarting"
DragOver="ListView_DragOver"
CanReorderItems="True"
DragItemsCompleted="ListView_DragItemsCompleted"
Drop="ListView_Drop" ItemsSource="{Binding Listing}"
/>
And here is the Code Behind for the ListView
private void ListView_DragItemsStarting(object sender, DragItemsStartingEventArgs e)
{
var item = string.Join(",", e.Items.Cast<string>());
e.Data.SetText(item);
e.Data.RequestedOperation = DataPackageOperation.Move;
}
private void ListView_DragOver(object sender, DragEventArgs e)
{
if (e.DataView.Contains(StandardDataFormats.Text))
{
e.AcceptedOperation = DataPackageOperation.Move;
}
}
private async void ListView_Drop(object sender, DragEventArgs e)
{
if (e.DataView.Contains(StandardDataFormats.Text))
{
var item = await e.DataView.GetTextAsync();
var destinationListView = sender as ListView;
var listViewItemsSource = destinationListView?.ItemsSource as ObservableCollection<string>;
if (listViewItemsSource != null)
{
listViewItemsSource.Add(item);
}
}
}
private void ListView_DragItemsCompleted(ListViewBase sender, DragItemsCompletedEventArgs args)
{
var item = string.Join(",", args.Items.Cast<string>());
var destinationListView = sender as ListView;
var listViewItemsSource = destinationListView?.ItemsSource as ObservableCollection<string>;
listViewItemsSource.Remove(item);
}
}
The Problem I have is finding a way to stop a ListView from becoming completely empty if I drag all the items out of the a ListView. Once the ListView becomes empty I can't go back and drag something into it.
The Second problem is when I drag an item and then let go of it in the same ListView it was dragged from then it deletes and does no re-add the item.
I think I need to add an If statement to the DragItemCompleted method to see If the source is the same as the target before removing the item.
Edit I seem to have fixed" the second problem by removing the CanReorderItemsProperty from the listView. I'm not sure why but it seems to have fixed up that issue. But now i can't reorder the lists :(
Look into this windows sample program https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/XamlDragAndDrop/cs
I have 2 different images and the idea is that when you click either of them you should get to a new page and the new page should show the image that you picked, I am not getting it to work. I know I can make 2 different pages but I want to refine my code as much as possible.
this is the code:
public PicturePage ()
{
image1.Clicked += OnButtonClicked; //x:name of my image in xaml.
image2.Clicked += OnButtonClicked; //x:name of my second image in xaml.
}
async void OnButtonClicked(Object sender, EventArgs args)
{
Navigation.PushAsync (new PictureDetailPage ()); //how will the code know what the user clicked?
}
Every Xamarin.Forms element has a StyleId property, which you can use to assign a user defined value for identifying the element.
In your XAML:
<Image x:Name="Image1" StyleId="Image1" ... />
and in the code behind:
async void OnButtonClicked(Object sender, EventArgs args)
{
Image image = (Image) sender;
// pass the value of the StyleId string to the detail page
Navigation.PushAsync (new PictureDetailPage (image.StyleId));
}
I have a combo box populated using dataset table adapters. I have a textbox and a button next to it. Onclick of this button the textbox value is added to the database. I want to refresh my Combobox once any new entry has been made. I did my research and figured out that I will have to Create an ObservableCollection and fill it with the data from DB. But since I am using dataset all the classes for each of the table is already present.
Here is my code:
XAML
<ComboBox Name="service" SelectedValuePath="Id" DisplayMemberPath="Service" ></ComboBox>
<TextBox Name="txtTobeAdded"></TextBox>
<Button Name="add" Content="Add" Click="add_Click"></Button>
C#
public partial class Window3 : Window
{
private SqlDatatsetTableAdapters.ServicesTableAdapter tableAdapterServices = new SqlDatatsetTableAdapters.ServicesTableAdapter();
public Window3()
{
InitializeComponent();
System.Data.DataView vw = tableAdapterServices.GetData().DefaultView;
service.ItemsSource = vw;
service.SelectedIndex = 0;
}
private void add_Click(object sender, RoutedEventArgs e)
{
tableAdapterServices.InsertQuery(txtTobeAdded.Text);
}
}
your scenario : Whatever changes to the database must be reflected to the combobox..
solution 1 : just call the another form as ShowDialog() instead of Show() and as soon as the child form is closed bind the datasource of the combobox again. as u can query the database again and retrieve the data again.
solution 2 : Just have a static List and send the newly added value to the Parent form from the child form using the Parent constructor.
try:
private void add_Click(object sender, RoutedEventArgs e)
{
tableAdapterServices.InsertQuery(txtTobeAdded.Text);
service.ItemsSource = tableAdapterServices.GetData().DefaultView;;
service.SelectedIndex = 0;
}
Its a lazy solution pushing the values back into the combo box. If you would like to learn the way to do it using an observable collection you will have to look at data Binding and the MVVM design pattern. More Info Found here
I need to retrieve components from a listbox item. Not from a Tap or selection changed events. Is there a simple way to achieve this?
If I remember correct, in Android you can just write:
layoutRoot.findViewById(R.id.name);
Is there a similar way to do this on Windows Phone?
Update: Here's what I tried so far, but does not work:
What Daniela said in option 5 seems to work when I have the ListBoxItem. So this works fine when I have for example a Tap event on the ListBoxItem:
private void ListBoxItem_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
ListBoxItem item = sender as ListBoxItem;
// I can now retrieve a component inside the ListBoxItem
TextBox textBox = item.FindName("myTextBox") as TextBox;
}
But I want to do this when not triggering any events from a ListBoxItem.
What JoonasL said looks like something I could use but I can't get it to work.
// will not compile ( Cannot implicitly convert type 'object' to... )
ListBoxItem item = x.Items[0];
// if cast the value will be null
ListBoxItem item = x.Items[0] as ListBoxItem;
// will return the object used to populate that ListBoxItem, not the actual ListBoxItem.
// item will have a ItemViewModel object.
List<ItemViewModel> list = ....
this.myListBox.ItemsSource = list;
var item = x.Items[0]
When searching on Google I found something that I could use to find a component inside a ListBoxItem but I think there should be a easier way. Here they use a VisualTreeHelper.
Edit:
add a name to your lisbox (x:Name="something")
Cast ALL items as a List or pick out an item and cast the item as the correct type. Example:
private void Button_Click(object sender, RoutedEventArgs e)
{
var list = yourListbox.Items;
var itemCastAsCorrectObjectInstance = (ItemViewModel)list.FirstOrDefault();
textblock.Text = itemCastAsCorrectObjectInstance.LineOne;
}
ItemViewModel is a class we have created, and a list of ItemViewModels are used as itemssource for the listbox.
Here is an app example I've made for you
There are several ways to do that (some of the examples are WPF, but code is quite similar, it's just to give you a general idea)
Create listbox in code and retrieve item as in the example provided my JoonasL
private void GetUserRecommendations()
{
var obj = _helper.GetList<Recommendations>(#"http://localhost:1613/Home/GetAllRecommendations");
_items.Clear();
foreach (var item in obj)
{
_items.Add(item);
}
itemListView.ItemsSource = _items;
}
Retrieve a selected item on a changed event (or other event bound to the listbox)
void ItemView_ItemClick(object sender, ItemClickEventArgs e)
{
var itemProperty = ((ListBoxItem) e.ClickedItem).SomeProperty;
}
Provide the listbox a name and access the items by refering to the name in the code
var item = itemListView.SelectedItem as SomeClass;
Access the selected item by binding to another element (XAML only)
<Border Margin="10" BorderBrush="Silver" BorderThickness="3" Padding="8">
<DockPanel>
<TextBlock>Choose a Color:</TextBlock>
<ComboBox Name="myComboBox" SelectedIndex="0">
<ComboBoxItem>Green</ComboBoxItem>
<ComboBoxItem>Blue</ComboBoxItem>
<ComboBoxItem>Red</ComboBoxItem>
</ComboBox>
<Canvas>
<Canvas.Background>
<Binding ElementName="myComboBox" Path="SelectedItem.Content"/>
</Canvas.Background>
</Canvas>
</DockPanel>
Search the layoutroot
var myTextBlock = (TextBlock)this.FindName("myTextBlock");
Or maybe something like:
private void Somepage_Loaded(object sender, RoutedEventArgs e)
{
if (SomeCondition())
{
var children = (sender as Panel).Children;
var child = (from Control child in children
where child.Name == "NameTextBox"
select child).First();
child.Focus();
}
ListBox x = new ListBox();
ListBoxItem item = x.Items[0];
Or do you want something else?
RadDataBoundListBox has an event called ItemTap (not sure about normal ListBox) but my solution went something like this:
private void FocusTextBox(object sender, ListBoxItemTapEventArgs e)
{
txtBox = e.Item.FindChildByType<TextBox>();
var item = itemListView.SelectedItem as PanoramaApp1.//Your Selected Item Type Here;
//Do Something With item Here
itemListView.SelectedItem = null;
}