How to get selected controls from GridView with SelectionMode=Multiple - c#

I have a GridView like this:
<GridView x:Name="list" ScrollViewer.VerticalScrollBarVisibility="Hidden" SelectionChanged="list_SelectionChanged" ItemsSource="{x:Bind Wallpapers}" SelectionMode="Multiple">
<GridView.ItemTemplate>
<DataTemplate x:DataType="data:ImageItem">
<StackPanel>
<Image FlyoutBase.AttachedFlyout="{StaticResource ImageMenuFlyout}" Width="150" Height="90" Source="{x:Bind img}" Tag="{x:Bind TagIndex}" Holding="Image_Holding" Tapped="Image_Tapped"/>
<Image Source="used.png" Height="15" Margin="0,-15,0,0" HorizontalAlignment="Left" Width="44" Visibility="{x:Bind Used, Mode=OneWay}"/>
</StackPanel>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
I need to get on the OnSelectionChanged method of the GrifView the visibility of the second Image control.
I need this because if the user select at least one item which have the second Image control visibility to "Visible", I have to enable a button.

Tried to recreate your example.
I assume you have a class called ImageItem. I created one with only the Used property:
public class ImageItem
{
public Visibility Used { get; set; }
}
My view is basically the same as yours, I used different ItemsSource name and only left in the Visibility binding of the second Image control:
<GridView x:Name="list" ScrollViewer.VerticalScrollBarVisibility="Hidden" SelectionChanged="List_OnSelectionChanged" ItemsSource="{x:Bind Items}" SelectionMode="Multiple">
<GridView.ItemTemplate>
<DataTemplate x:DataType="local:ImageItem">
<StackPanel>
<Image Width="150" Height="90" />
<Image Height="15" Margin="0,-15,0,0" HorizontalAlignment="Left" Width="44" Visibility="{x:Bind Used, Mode=OneWay}" />
</StackPanel>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
I bound it to the following collection:
Items = new ObservableCollection<ImageItem>
{
new ImageItem() { Used = Visibility.Visible },
new ImageItem() { Used = Visibility.Visible },
new ImageItem() { Used = Visibility.Collapsed },
};
So only the third item's second Image is hidden.
My selection changed handler is the following:
private void List_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
var gridView = sender as GridView;
if (gridView != null)
{
var isAtLeastOneVisible =
gridView.SelectedItems.OfType<ImageItem>().Any(i => i.Used == Visibility.Visible);
}
}
So isAtLeastOneVisible will be true if you select at least the first and/or the second item in the list, and will be false if you only select the third item.

Related

How to get a selected item in a list box with bindings?

I have a wpf application in c# and my problem is now I have a Listbox with bindings and my question is how can I get the text from the textbox in the Listbox?
My Listbox XAML:
<ListBox x:Name="chats_lb_friends" ItemsSource="{Binding Friends_pic}" Height="870" Width="280" Background="{x:Null}" BorderBrush="{x:Null}" Foreground="#FF535664" FontSize="18" FontFamily="/Nextopia Launcher v.2.0;component/fonts/#Mont DEMO" FontWeight="Bold" IsSynchronizedWithCurrentItem="False" MinWidth="280" SelectionChanged="chats_lb_friends_SelectionChanged_1">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel x:Name="chats_lb_friends_stackpanel" Orientation="Horizontal">
<Ellipse x:Name="chats_lb_friends_img" Width="25" Height="25" Stroke="{Binding status}" StrokeThickness="2">
<Ellipse.Fill>
<ImageBrush Stretch="Fill" ImageSource="{Binding imagePath}"/>
</Ellipse.Fill>
</Ellipse>
<TextBlock x:Name="chats_lb_friends_txt" Text="{Binding username}" Margin="5,0,0,0" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
What do I want:
ListBoxItem MyItem = chats_lb_friends.SelectedItem as ListBoxItem;
if(MyItem != null)
{
StackPanel sp = MyItem.Content as StackPanel;
if(sp != null && sp.Children.Count > 0)
{
TextBlock textBlock = sp.Children[0] as TextBlock;
if(textBlock != null)
{
string text = textBlock.Text;
}
}
}
But this is not working have anyone an idea why?
Thanks in the advance and sorry for my English
Assuming you have a PersonViewModel with a public string property username.
The itemssource of your lisbox doesn't seem to be bound. But let's assume you can have a window viewmodel with 2 public properties:
public ObservableCollection<PersonViewModel> People {get;set;} = new ObservableCollection<PersonViewModel>()
public PersonViewModel SelectedPerson {get;set;}
So you can bind SelectedItem of the listBox to SelectedPerson
<ListBox SelectedItem="{Binding SelectedPerson" ItemsSource="{Binding People}"
Then you can do:
var name = SelectedPerson.username;
You will also want some null checking maybe
var name = SelectedPerson?.username ?? "";
You should implement inotifypropertychanged on all viewmodels and you will also likely to want to raise notifypropertychanged from the setters of your viewmodel properties.
More about working with selected items using mvvm here:
https://social.technet.microsoft.com/wiki/contents/articles/30564.wpf-uneventful-mvvm.aspx#Select_From_List_IndexChanged

Wpf listview where listviewitem is a custom button

I have a problem. I have a list view in my xaml:
<ListView
Margin="0 10 0 0"
DockPanel.Dock="Top"
ItemsSource="{Binding Items}"
ScrollViewer.VerticalScrollBarVisibility="Hidden"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
BorderThickness="0"
SelectedItem="{Binding SelectedItem, Mode=TwoWay}">
<ListView.ItemTemplate>
<DataTemplate>
<local:ItemView/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
My item view looks like this (which is in UserControl tag):
<buttons:MyButton
cal:Message.Attach="DoSomething">
<buttons:MyButton.Visual>
<DockPanel
HorizontalAlignment="Left">
<local:Image
DockPanel.Dock="Left"
CountryCode="{Binding Source}"/>
<TextBlock
DockPanel.Dock="Left"
VerticalAlignment="Center"
Padding="15 0 0 0"
FontFamily="{StaticResource MediumFont}"
FontSize="16"
Foreground="{StaticResource DarkText}"
Text="{Binding TextValue}" />
</DockPanel>
</buttons:MyButton.Visual>
</buttons:MyButton>
Now the problem is that when i click on the list item, my selectedItem is not set. It always null unless I click on the very edge of the list item, then it sets the selected value, but i have to click again in the middle of the item to call the action I want.
My question is: How can I make my list view item on click (on the whole item plot) set the selected item and call the action I want?
P.S. I am using Caliburn Micro if this helps...
If you don't mind using code behind or a view model, you could do something like this:
<ListView.ItemTemplate>
<DataTemplate>
<Button BorderBrush="Transparent" Background="Transparent" Focusable="False">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:InvokeCommandAction Command="{Binding DataContext.ClickCommand, ElementName=ListViewName}" CommandParameter="{Binding}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<!-- YOUR TEMPLATE HERE -->
<Button.Template>
</DataTemplate>
</ListView.ItemTemplate>
This is a view/control related thing. You could handle the Click event for the Button and explicitly set the IsSelected property of the parent ListViewItem container like this:
private void OnClick(object sender, RoutedEventArgs e)
{
var listViewItem = FindParent<ListViewItem>(sender as DependencyObject);
if (listViewItem != null)
listViewItem.IsSelected;
}
private static T FindParent<T>(DependencyObject dependencyObject) where T : DependencyObject
{
var parent = VisualTreeHelper.GetParent(dependencyObject);
if (parent == null) return null;
var parentT = parent as T;
return parentT ?? FindParent<T>(parent);
}
XAML:
<ListView.ItemTemplate>
<DataTemplate>
<local:ItemView ButtonBase.Click="OnClick"/>
</DataTemplate>
</ListView.ItemTemplate>
Or you could set the SelectedItem property of the ListView to the DataContext of the element:
private void OnClick(object sender, RoutedEventArgs e)
{
FrameworkElement fe = sender as FrameworkElement;
if (fe != null)
listView.SelectedItem = fe.DataContext;
}
XAML:
<ListView x:Name="listView" ... />
I know this is an old question, but what I think you were looking for is something like this
<ListView ItemsSource="{Binding ListViewItemTemplates}">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel>
<Button x:Name="StartPage">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<cal:Action.Target>
<cal:ActionMessage MethodName="StartPage">
<cal:Parameter Value="{Binding}" />
</cal:ActionMessage>
</cal:Action.Target>
</i:EventTrigger>
</i:Interaction.Triggers>
<Button.Template>
<ControlTemplate>
<StackPanel Width="210" Orientation="Horizontal">
<Image Source="{Binding Path=Source}"
Stretch="None" />
<TextBlock Text="{Binding Path=Name}" />
</StackPanel>
</ControlTemplate>
</Button.Template>
</Button>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
<ListView/>
Then you can easily bind this with the following
private ObservableCollection<ListViewItemTemplate> listViewItemTemplates;
public ObservableCollection<ListViewItemTemplate> ListViewItemTemplates
{
get => listViewItemTemplates;
set
{
listViewItemTemplates = value;
this.OnPropertyChanged("ListViewItemTemplates");
}
}
Where ListviewItemTemplate is a class consisting of two strings Name and Source

Xaml - Bind listviewitem source object

I use an observableCollecion in my VM. This Collection is bind into my view in a ListView. In my items I try to get the element who create this item. Add it in my commandParameter and do the thing.
Here's my VM :
public RelayCommand<SelectionCommandParameter> CmdRemoveFromQuiz { get; set; }
public ObservableCollection<Question> SelectedQuiz
{
get { return _selectedQuiz; }
set
{
_selectedQuiz = value;
RaisePropertyChanged("SelectedQuiz");
}
}
private void RemoveFromQuiz(SelectionCommandParameter selection)
{
if (selection.Parameter is Question)
{
ObservableCollection<Question> tempQuiz = SelectedQuiz;
Question _question = (Question)selection.Parameter;
tempQuiz.Remove(_question);
SelectedQuiz = tempQuiz;
}
}
The problem start with the RemoveBtn I start the command, and selection stay null I want to get the ObservableCollection<Question> object use in my ListViewitem
Now My View :
<userControls:CharmFlyout
x:Name="cfoQuizList"
x:Uid="QuizListCreatingPageFlyout"
Heading="Question Multiple"
HorizontalAlignment="Left"
Grid.Column="0"
Grid.RowSpan="2"
Style="{StaticResource stlAddRecipientFlyout}">
<tut:TutorialAwareListView x:Name="gvQuizItem"
ItemsSource="{Binding SelectedQuiz}"
IsItemClickEnabled="True"
CanReorderItems="True"
SelectionMode="None"
ManipulationMode="TranslateRailsX">
<ListView.ItemTemplate>
<DataTemplate x:Name="DTQuizItem">
<Grid HorizontalAlignment="Left" Width="{StaticResource RectangleTileWidth}" Height="{StaticResource RectangleTileHeight}"
Margin="0 0 0 0" Background="{StaticResource OrangeBackgroundThemeBrush}">
<Grid Grid.Column="1">
<Button x:Name="RemoveBtn" Content="X" HorizontalAlignment="Right" VerticalAlignment="Top" Width="40" Height="40"
BorderThickness="0" Command="{Binding DataContext.CmdRemoveFromQuiz, ElementName=gvQuizItem}" CommandParameter="{Binding Question}"/>
<maxCtrls:MaxAutoScrollingContentPresenter VerticalAlignment="Center"
ScrollingDuration="{Binding Name, Converter={StaticResource TextToTimeToReadShortFormatConverter}}"
ScrollingBeginTime="0:0:2">
<TextBlock Text="{Binding Name}" FontWeight="SemiBold"
Foreground="{StaticResource WhiteBackground}"
Margin="20,5,10,5" VerticalAlignment="Center" TextWrapping="Wrap"/>
</maxCtrls:MaxAutoScrollingContentPresenter>
</Grid>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</tut:TutorialAwareListView>
</userControls:CharmFlyout>
The TutorialAwareListView Work exactly like a ListView. I use it juste to point the element while the tutorial is running.
It's a Windows Store App !! I can't do all the thing we would like to.
You should change your SelectionMode="None" to Single or Multiply.
And make new ObservableCollection for selected items. You bind just ItemsSource="{Binding SelectedQuiz}". Bind SelectedItems="{...}"

How to add checked contact in list Windows Phone 8?

i am trying to add contacts in list as my code is,
<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<StackPanel Height="Auto" Width="Auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0,0,0,10">
<TextBlock x:Name="ContactResultsLabel" Text="results are loading..." Style="{StaticResource PhoneTextLargeStyle}" TextWrapping="Wrap"></TextBlock>
<ListBox x:Name="ContactResultsData" ItemsSource="{Binding listOfContacts}" Height="293" Margin="24,0,0,0">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox Name="contactChk" IsChecked="false" Foreground="Black" Background="Black" BorderBrush="White"></CheckBox>
<TextBlock x:Name="ContactResultsName" Text="{Binding Name}" FontSize="50"></TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
not able to get contacts under list box i am using this method on button click,
private void GetSelectedCheckObjItem()
{
try
{
for (int i = 0; i < ContactResultsData.Items.Count; i++)
{
// Get a all list items from listbox
ListBoxItem ListBoxItemObj = (ListBoxItem)ContactResultsData.ItemContainerGenerator.ContainerFromItem(ContactResultsData.Items[i]);
// find a ContentPresenter of that list item.. [Call FindVisualChild Method]
ContentPresenter ContentPresenterObj = FindVisualChild<ContentPresenter>(ListBoxItemObj);
// call FindName on the DataTemplate of that ContentPresenter
DataTemplate DataTemplateObj = ContentPresenterObj.ContentTemplate;
CheckBox Chk = (CheckBox)DataTemplateObj.FindName("contactChk", ContentPresenterObj);
// get a selected checkbox items.
if (Chk.IsChecked == true)
{
MessageBox.Show(Chk.Content.ToString().Trim());
}
}
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
I got this method from google it looks fine but issue is that i am not getting "Findname" in this line,
CheckBox Chk = (CheckBox)DataTemplateObj.FindName("contactChk", ContentPresenterObj);
i also tried this one,
<ListBox x:Name="ContactResultsData" SelectionMode="Multiple" ItemsSource="{Binding listOfContacts}" Height="293" Margin="24,0,0,0">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox Name="contactChk"
IsChecked={Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}},
Path=IsSelected}"
Foreground="Black" Background="Black" BorderBrush="White">
</CheckBox>
<TextBlock x:Name="ContactResultsName" Text="{Binding Name}" FontSize="50"></TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
On using this i am not getting these properties,
Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}
and properties i am getting are,
Self and TemplatedParent
Is there any alternative for adding contact in list. Well i am alerting on checkbox click,
private void contactChk_Checked(object sender, RoutedEventArgs e)
{
CheckBox chk2 = (CheckBox)sender;
MessageBox.Show("" + chk2.IsChecked);
count++;
}
perhaps i can add contact in list from this method
Hopes for your suggestion
Thanks
using Microsoft.Phone.UserData;
//Use this name space
FOllow the below //improvise a little bit
Contacts cons = new Contacts();
foreach(var c in con)
{
a.cnts.Add(new Contactss()
{
name=c.name,
number=c.phone
});
}
lstbxk.ItemsSource = a.cnts;

How to remove a custom item from a listBox and ObservableCollection when click on a button

I have the listBox and a ObservableCollection. The listBox.ItemSource (listNotify.ItemSource) is set to that ObservableCollection (errosList).
The problem that i have is that i don`t know how to remove the correct element from errorsList when the user click on the button with content x from listBox. For the item of the listBox i use a ItemTemplate, inside a stackPanel and in stackPanel i have a button.
Bellow is the XAML code:
<ListBox x:Name="listNotify">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Height="35">
<Image Height="16" Source="/Template;component/Resources/error.png" Stretch="Fill" VerticalAlignment="Top" Width="16"/>
<StackPanel Orientation="Vertical">
<HyperlinkButton Content="{Binding ErrorHeader}" HorizontalAlignment="Left" Height="16" Width="125"/>
<TextBlock Text="{Binding ErrorMessage}" HorizontalAlignment="Left" Width="405" d:LayoutOverrides="VerticalAlignment" />
</StackPanel>
<Button Content="x" Width="20" Height="20" Click="removeError_Click"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
The code is from a silverlight 4 project.
Thanks.
private void removeError_Click(object sender, RoutedEventArgs e) {
FrameworkElement fe = sender as FrameworkElement;
if (null != fe) {
_observableCollection.Remove((YourType)fe.DataContext);
}
}
Should do what your looking for. Replace YourType with the type you declared in the ObservableCollectiion.
Don't you have an ID-like property in your Items of the errorsList-Collection? Then you could use the Tag-Property of the Button to archieve this:
<Button Content="x" Width="20" Height="20" Tag="{Binding ID}" Click="Button_Click" />
and in the click-event of the button:
string id = ((Button) sender).Tag.ToString();
var itemToRemove = errorsList.Where(x => x.ID == id).First();
errorsList.Remove(itemToRemove);
Hope that helps

Categories

Resources