I have a LongListSelector that is binded with ObservableCollection of some kind of Items. Items have many different properties.
<LongListSelector Name="DraftControl" MouseLeftButtonDown="GoToEditDraft">
<LongListSelector.ItemTemplate>
<DataTemplate>
...
</DataTemplate>
<LongListSelector.ItemTemplate>
</LongListSelector>
It has an event handler. But it gets as sender the whole LongListSelector, not a particular item. How to add event handler for all items?
Here is a handler's code:
private void GoToEditDraft(object sender, MouseButtonEventArgs mouseButtonEventArgs)
{
var clickerdItem = (LongListSelector)sender;
MessageBox.Show(clickedItem.SelectedItem.ToString());
}
So, trying to get SelectedItem this way throws NullReferenceException.
Data template:
<DataTemplate>
<Grid Margin="10" toolkit:TiltEffect.IsTiltEnabled="True">
<Grid.Background>
<SolidColorBrush Color="LightGray" Opacity="0.8"/>
</Grid.Background>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="120"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition MaxHeight="100"/>
<RowDefinition MaxHeight="30"/>
</Grid.RowDefinitions>
<TextBlock TextWrapping="Wrap" FontSize="28" Foreground="{StaticResource CustomApplicationTextBrush}" Text="{Binding Title, Converter={StaticResource SanitizeString}}" Margin="10,10,10,0" Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2"/>
<Image Source="/Images/no-image.png" Stretch="UniformToFill" MaxHeight="100" Margin="10,10,0,10" Grid.RowSpan="1" Grid.Column="0" Grid.Row="1" VerticalAlignment="Top"/>
<TextBlock TextWrapping="Wrap" FontSize="18" Foreground="{StaticResource CustomApplicationTextBrush}" TextTrimming="WordEllipsis" Text="{Binding Address, Converter={StaticResource SanitizeString}}" Margin="10,0,10,10" Grid.Column="1" Grid.Row="1" VerticalAlignment="Top"/>
</Grid>
</DataTemplate>
Binding:
ObservableCollection<Item> draftItems = new ObservableCollection<Item>();
var draftStorage = IsolatedStorageFile.GetUserStoreForApplication();
IReadOnlyList<StorageFile> allDrafts = await draftFolder.GetFilesAsync();
foreach (StorageFile file in allDrafts)
{
using (var stream = new IsolatedStorageFileStream("Drafts\\" + file.Name, FileMode.Open, draftStorage))
{
var fileReader = new StreamReader(stream);
string jsonContents = fileReader.ReadLine();
Item readedItem = JsonConvert.DeserializeObject<Item>(jsonContents);
draftItems.Add(readedItem);
fileReader.Close();
}
}
DraftControl.ItemsSource = draftItems;
Try this.
private void DraftControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var myItem = ((Item)(sender as LongListSelector).SelectedItem);
}
Subscribe to LongListSelectors SelectionChangedEvent rather
<LongListSelector Name="DraftControl" SelectionChanged="lls_SelectionChanged">
<LongListSelector.ItemTemplate>
<DataTemplate>
...
</DataTemplate>
<LongListSelector.ItemTemplate>
</LongListSelector>
and get the item in the code behind
private void lls_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var myItem = ((LongListSelector) sender).SelectedItem as Type;
}
Related
This is how I'm currently populating a combo box. Is there any way to be able to use a list like this, but also add a little color preview box to the left of the item?
private void PantsColor_ComboBox_Loaded(object sender, RoutedEventArgs e)
{
List<string> data = new List<string>();
data.Add("Blue");
data.Add("Red");
data.Add("Green");
data.Add("Orange");
data.Add("Pink");
data.Add("Purple");
var pantsColorComboBox = sender as ComboBox;
pantsColorComboBox.ItemsSource = data;
pantsColorComboBox.SelectedIndex = 0;
}
A color preview box to the left of the item can be added in ComboBox.ItemTemplate:
private void ColorComboBoxLoaded(object sender, RoutedEventArgs e)
{
var cbo = sender as ComboBox;
if (cbo == null)
return;
cbo.ItemsSource = new List<string> { "Blue", "Red", "Green", "Orange", "Pink", "Purple" };
}
<ComboBox SelectedIndex="0"
Loaded="ColorComboBoxLoaded">
<ComboBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Border Background="{Binding}" Height="20" Width="24" Margin="2"/>
<TextBlock Grid.Column="1" Margin="5,0" VerticalAlignment="Center" Text="{Binding}"/>
</Grid>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Result:
note that SelectedIndex can be set in xaml. also note, that even if Background is set with string value, it is still applied properly because there is a built-in converter which creates Brush from color name (or hex ARGB code).
also all items can be set in xaml without any event handlers in code-behind:
<ComboBox SelectedIndex="0">
<ComboBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Border Background="{Binding}" Height="20" Width="24" Margin="2"/>
<TextBlock Grid.Column="1" Margin="5,0" VerticalAlignment="Center" Text="{Binding}"/>
</Grid>
</DataTemplate>
</ComboBox.ItemTemplate>
<ComboBox.Items>
<system:String>Blue</system:String>
<system:String>Red</system:String>
<system:String>Green</system:String>
<system:String>Orange</system:String>
<system:String>Pink</system:String>
<system:String>Purple</system:String>
</ComboBox.Items>
</ComboBox>
You need to use Datatemplate for Combobox items.
<ComboBox x:Name="pantsColorComboBox" Height="30" Width="200">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Width="20" Height="20" Background="{Binding Key}"></TextBlock>
<TextBlock Text="{Binding Value}"></TextBlock>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Your itemsource will be modified to a dictionary.
var data = new Dictionary<SolidColorBrush,string>();
data.Add(Brushes.Blue,"Blue");
data.Add(Brushes.Red,"Red");
data.Add(Brushes.Green, "Green");
data.Add(Brushes.Orange, "Orange");
data.Add(Brushes.Pink, "Pink");
data.Add(Brushes.Purple, "Purple");
var pantsColorComboBox = sender as ComboBox;
pantsColorComboBox.ItemsSource = data;
pantsColorComboBox.SelectedIndex = 0;
So I really don't know how to ask this question but this is what I am trying to achieve. I got a list box with this code:
<ListBox
x:Name="lb"
Margin="0,0,0,100"
Background="#212B34"
BorderThickness="0"
Padding="0"
SelectionChanged="lb_SelectionChanged">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
<Setter Property="Padding" Value="0,8,0,8"></Setter>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Height="152" BorderThickness="10,0,0,0" BorderBrush="#2E66AA" Background="#161C22" Padding="8,8,8,8">
<Grid.RowDefinitions>
<RowDefinition Height="30"></RowDefinition>
<RowDefinition Height="25"></RowDefinition>
<RowDefinition Height="25"></RowDefinition>
<RowDefinition Height="60"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="4*"></ColumnDefinition>
<ColumnDefinition Width="2*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Foreground="#2E66AA" Text="{Binding Location}" FontSize="18" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2"></TextBlock>
<TextBlock Foreground="White" Text="{Binding Description}" FontSize="12" Grid.Row="1" Grid.RowSpan="3" Grid.Column="0" TextTrimming="WordEllipsis" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" TextWrapping="Wrap"></TextBlock>
<TextBlock Foreground="White" Text="{Binding Date}" FontSize="18" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Stretch" TextAlignment="Right"></TextBlock>
<TextBlock Foreground="White" Text="{Binding Time}" FontSize="18" Grid.Row="2" Grid.Column="1" HorizontalAlignment="Stretch" TextAlignment="Right"></TextBlock>
<TextBlock Foreground="#2E66AA" FontSize="24" Grid.Row="3" Grid.Column="1" VerticalAlignment="Bottom" HorizontalAlignment="Stretch" TextAlignment="Right">
<Run Text="$ "/>
<Run Text="{Binding Price}"/>
<Run Text=";"/>
</TextBlock>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
And use Azure App Service for my database. I bind the data to the listbox using itemsource:
private async void loadEvents_Click(object sender, RoutedEventArgs e)
{
IMobileServiceTable<eventTable> eventList = App.MobileService.GetTable<eventTable>();
MobileServiceCollection<eventTable, eventTable> events = await eventList
.Where(ProductTable => ProductTable.id != "")
.ToCollectionAsync();
lb.ItemsSource = events;
}
What I want to do is when a user selects a listbox item he needs to be redirected to a new page. But on this new page I need the id of the event (row in the database). So I can use this id to retrieve all further information of the event.
Maybe I need to bind the id to the listboxitem by using {Binding id} but what do I bind it to? A textblock wich I can make invisible? And if I bind it to something how do I retrieve it?
This is what I use to redirect the user to a new page:
private void lb_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
this.Frame.Navigate(typeof(eventPage));
}
If there is a different way to get al information about the selected event please tell.
I would really appreciate your help.
Get the SelectedItem from lb.SelectedItem and typecast to its corresponding class. From that, you can get the selected item's Ip. Now pass this value as the second parameter to Frame.Navigate.
private void lb_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
this.Frame.Navigate(typeof(eventPage), (eventTable)lb.SelectedItem);
}
To get this value on the next page
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
var selectedItem = (eventTable)e.Parameter;
}
I have the following TabControl:
<TabControl Name="tabControl" Grid.Row="0" MinWidth="270" HorizontalAlignment="Stretch" ItemsSource="{Binding Counters}" ContentTemplate="{StaticResource templateForTheContent}"
ItemTemplate="{StaticResource templateForTheHeader}">
</TabControl>
It uses this DataTemplate:
<Window.Resources>
<DataTemplate x:Key="templateForTheContent" >
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ListBox Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="0"
ItemsSource="{Binding}"
SelectionMode="Multiple"
BorderThickness="1" BorderBrush="#FF8B8B8B" SelectionChanged="ListBox_SelectionChanged_1">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock>
<Run Text="{Binding CounterName, Mode=OneWay}" />
<Run Text="{Binding InstanceName, Mode=OneWay}" />
</TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button Name="RAMSelectAllButton" Margin="0,10,0,0" Grid.Column="0" Grid.Row="1">
<TextBlock Text="SELECT ALL"/>
</Button>
<Button Name="RAMUnSelectAllButton" Margin="0,10,0,0" Grid.Column="1" Grid.Row="1">
<TextBlock Text="UNSELECT ALL"/>
</Button>
</Grid>
</DataTemplate>
<DataTemplate x:Key="templateForTheHeader" >
<TextBlock Text="{Binding CategoryName}"/>
</DataTemplate>
</Window.Resources>
It works as expected, binding works well, everything would be totally fine if this issue wasn't present:
Each time I switch a tab in my TabControl, selected items of a ListBox in my previous tab are reset - so when I go back to that tab - nothing is selected.
How to fix this?
//EDIT
here's my ListBox_SelectionChanged_1 method:
private void ListBox_SelectionChanged_1(object sender, SelectionChangedEventArgs e)
{
System.Windows.Controls.ListBox listBoxTemp = sender as System.Windows.Controls.ListBox;
PerformanceCounter counterTemp = (PerformanceCounter)listBoxTemp.Items[0];
if (!appData.SelectedCounters.ContainsKey(counterTemp.CategoryName))
appData.SelectedCounters.Add(counterTemp.CategoryName, new List<PerformanceCounter>());
appData.SelectedCounters[counterTemp.CategoryName].Clear();
foreach (PerformanceCounter counter in listBoxTemp.SelectedItems)
{
appData.SelectedCounters[counterTemp.CategoryName].Add(counter);
}
}
ListBox is bound to Counters, which is Observable Collection:
public ObservableCollection<ObservableCollection<PerformanceCounter>> Counters
{
get { return _Counters; }
}
ObservableCollection<ObservableCollection<PerformanceCounter>> _Counters = new ObservableCollection<ObservableCollection<PerformanceCounter>>();
(i am not familiar with TabControls, or WPF for that matter, but i would suggest a solution like this:)
Backup the selected items of your ListBox in a Dictionary.
var selectionBackups = new Dictionary<ListBox, IEnumerable<ListBoxItem>>();
I'd keep this field updated in ListBox_SelectionChanged_1(). Whenever you enter a Tab, overwrite the concerned ListBox's selection.
void TabEnter(object sender, TabEventArgs e)
{
ListBox lb = ... //acquire the current Listbox
OverwriteSelection(lb, selectionBackups[lb]); //set the ListBox's selection
}
(You might want to prevent the ListBox_SelectionChanged_1() from triggering when you restore the selection. That could be done like this:
bool auto_select = false; //set this to true while editing selections
private void ListBox_SelectionChanged_1(object sender, SelectionChangedEventArgs e)
{
if(auto_select)
return;
...
}
)
I have this wpf code for my listbox item:
<ListBox x:Name="icTodoList" ItemsSource="{Binding ListControleMachine}" Grid.Column="3">
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderBrush="{Binding borderColor}" BorderThickness="2" Margin="0,0,0,1">
<Grid Margin="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="120"/>
<ColumnDefinition Width="130"/>
<ColumnDefinition Width="120"/>
<ColumnDefinition Width="120"/>
<ColumnDefinition Width="120"/>
<ColumnDefinition Width="120"/>
</Grid.ColumnDefinitions>
<CheckBox x:Name="check_action" Content="" HorizontalAlignment="Left" VerticalAlignment="Top" IsChecked="{Binding ActionCheked,Mode=TwoWay}"/>
<Ellipse x:Name="E_Ping" HorizontalAlignment="Left" Fill="{Binding PingDotColor}" Height="10" Width="10" Margin="2,4,0,0" VerticalAlignment="Top" RenderTransformOrigin="0.2,-1.182" Grid.Column="1"/>
<TextBlock Text="{Binding titlePing}" Grid.Column="2" MouseDown="TextBlock_MouseDown" Tag="{Binding ComputerName}"/>
<TextBlock Text="{Binding titlePing}" Grid.Column="2" MouseDown="TextBlock_MouseDown" Tag="{Binding ComputerName}"/>
<TextBlock Text="{Binding titleDcai}" Grid.Column="3" MouseDown="TextBlock_MouseDown" Tag="{Binding ComputerName}"/>
<TextBlock Text="{Binding titleAd}" Grid.Column="4" MouseDown="TextBlock_MouseDown" Tag="{Binding ComputerName}"/>
<TextBlock Text="{Binding FPACtitle}" Grid.Column="5" MouseDown="TextBlock_MouseDown" Tag="{Binding ComputerName}"/>
<TextBlock Text="{Binding titleMcAfee}" Grid.Column="6" MouseDown="TextBlock_MouseDown" Tag="{Binding ComputerName}"/>
<TextBlock Text="{Binding gkUser}" Grid.Column="7" MouseDown="TextBlock_MouseDown" Tag="{Binding ComputerName}"/>
<TextBlock Text="{Binding titleservicestat}" Grid.Column="8" MouseDown="TextBlock_MouseDown" Tag="{Binding ComputerName}"/>
</Grid>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
As you can see I have a "TextBlock_MouseDown" on each textbox
Then the c# code.
private void TextBlock_MouseDown(object sender, MouseButtonEventArgs e)
{
TextBlock t = sender as TextBlock;
DetailedView.DataContext = ListControleMachine.Where(x => x.ComputerName == t.Tag.ToString());
DetailedView.Visibility = System.Windows.Visibility.Visible;
}
Ok, so it does what I need basically it pop a view with data rebinded to it.
but I'm pretty sure its not a clean way to do it.
first I don't wont event on each textblock but on the listboxitem it self (but I don't know how to pass computername argument this way).
second and may bee my only problem I think I don't have to search my collection and rebind my new view with this:
DetailedView.DataContext = ListControleMachine.Where(x => x.ComputerName == t.Tag.ToString());
for be clear how to click an item template and pop a view that will contain actual listbox item binded data?
try set DataContext via binding to SelectedItem of ListBox
<DetailedView DataContext="{Binding Path=SelectedItem, ElementName=icTodoList, Mode=OneWay}"/>
or equivalent code
var binding = new Binding
{
Path = new PropertyPath("SelectedItem"),
ElementName = "icTodoList",
Mode = BindingMode.OneWay
};
BindingOperations.SetBinding(DetailedView, Control.DataContextProperty, binding);
another approach
ListBox has SelectionChanged event
<ListBox Name="icTodoList"
SelectionChanged="IcTodoList_OnSelectionChanged">
</ListBox>
event handler
private void IcTodoList_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
DetailedView.DataContext = icTodoList.SelectedItem;
DetailedView.Visibility = System.Windows.Visibility.Visible;
}
Tag values and TextBlock_MouseDown handler will be not necessary
xmal code:
<ListBox x:Name="listbox2" Margin="0,0" SelectionChanged="listbox2_SelectionChanged" Hold="listbox2_Hold" >
<ListBox.ItemContainerStyle >
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderThickness="0,0,0,1" BorderBrush="Gray">
<Grid Width="auto" HorizontalAlignment="Stretch" >
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock VerticalAlignment="Center" FontSize="40" Grid.Column="1" Grid.Row="0" Foreground="White" Text="{Binding NAME}"></TextBlock>
<TextBlock VerticalAlignment="Center" FontSize="25" Grid.Column="1" Grid.Row="1" Foreground="Blue" Text="{Binding PHONE}"></TextBlock>
<Image Name="c1" HorizontalAlignment="Left" VerticalAlignment="Top" Width="100" Height="100" Stretch="Fill" Margin="0" Source="{Binding IMGS}" Grid.RowSpan="2" Grid.Column="0" />
</Grid>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
class list which is bind to list box is
List < contactsclass > contacts = new List < contactsclass >();
PHONE and NAME are getter setter of the contactclass's variables
how can i get this variable's value on hold event of listbox .. i am trying following code
private void listbox2_Hold(object sender, System.Windows.Input.GestureEventArgs e)
{
//contextmenucontact = (contactsclass)(sender as ListBox).DataContext;
contextmenucontact = (contactsclass)listbox2.SelectedItem;
MessageBox.Show(contextmenucontact.name);
}
if is just the selected item is just use the ToString Function, see this:
if (listBox1.SelectedItem != null)
{
string itemText = listBox1.SelectedItem.ToString();
contextmenucontact = new contactsclass();
contextmenucontact.name = itemText;
MessageBox.Show(contextmenucontact.name);
}