WPF UniformGrid dynamic content - c#

I have a uniformgrid which i want to dyanmically show contents/view.
It can show either 1, 2, 4, or 6 contents. I set my uniformgrid row, col binding, and the content visibility binding.
This does NOT work in the case of views/contents,
but it DOES WORK in the case for rectangles. Why is that?
How do i modify it to work with views/contents.
Sample MainWindow.xaml code.....
<StackPanel>
<ComboBox HorizontalAlignment="Left" Width="50" SelectedIndex="{Binding SelectedIndex}">
<ComboBoxItem IsSelected="True" Content="1" />
<ComboBoxItem Content="2" />
<ComboBoxItem Content="4" />
<ComboBoxItem Content="6" />
</ComboBox>
<!-- NOT CORRECT, SHOWS 6 ITEMS ALWAYS -->
<UniformGrid Rows="{Binding ScreenRows}" Columns="{Binding ScreenCols}">
<local:ScreenView Grid.Row="0" Grid.Column="0" Visibility="{Binding VisibleScreen[0]}" />
<local:ScreenView Grid.Row="0" Grid.Column="1" Visibility="{Binding VisibleScreen[1]}" />
<local:ScreenView Grid.Row="0" Grid.Column="2" Visibility="{Binding VisibleScreen[2]}" />
<local:ScreenView Grid.Row="1" Grid.Column="0" Visibility="{Binding VisibleScreen[3]}" />
<local:ScreenView Grid.Row="1" Grid.Column="1" Visibility="{Binding VisibleScreen[4]}" />
<local:ScreenView Grid.Row="1" Grid.Column="2" Visibility="{Binding VisibleScreen[5]}" />
</UniformGrid>
<!-- OK, SHOWS 1,2,4, or 6 RECT DEPENDING ON SelectedIndex -->
<UniformGrid Rows="{Binding ScreenRows}" Columns="{Binding ScreenCols}">
<Rectangle Width="20" Height="20" Grid.Row="0" Grid.Column="0" Fill="Red" Visibility="{Binding VisibleScreen[0]}" />
<Rectangle Width="20" Height="20" Grid.Row="0" Grid.Column="1" Fill="Orange" Visibility="{Binding VisibleScreen[1]}" />
<Rectangle Width="20" Height="20" Grid.Row="0" Grid.Column="2" Fill="Yellow" Visibility="{Binding VisibleScreen[2]}" />
<Rectangle Width="20" Height="20" Grid.Row="1" Grid.Column="0" Fill="Green" Visibility="{Binding VisibleScreen[3]}" />
<Rectangle Width="20" Height="20" Grid.Row="1" Grid.Column="1" Fill="Blue" Visibility="{Binding VisibleScreen[4]}" />
<Rectangle Width="20" Height="20" Grid.Row="1" Grid.Column="2" Fill="Violet" Visibility="{Binding VisibleScreen[5]}" />
</UniformGrid>
</StackPanel>
Basically, i have a combobox. If I select 1, my ViewModel will dynamically change rows=1, cols=1, with 1st content Visible, and others collapse. It works in the case for Rectangles, but NOT views. Why is that? How to fix it so that it works for views?
Anyone curious, here is the code (Prism MVVM) in MainWindowViewModel
class MainWindowViewModel : BindableBase
{
private const int SCREEN_MAX = 6;
private int screenRows = 1;
public int ScreenRows
{
get { return screenRows; }
set { SetProperty(ref screenRows, value); }
}
private int screenCols = 1;
public int ScreenCols
{
get { return screenCols; }
set { SetProperty(ref screenCols, value); }
}
private Visibility[] visibleScreen = new Visibility[SCREEN_MAX];
public Visibility[] VisibleScreen
{
get { return visibleScreen; }
set { SetProperty(ref visibleScreen, value); }
}
private int selectedIndex;
public int SelectedIndex
{
get { return selectedIndex; }
set
{
SetProperty(ref selectedIndex, value);
ChangeScreen(selectedIndex);
}
}
private void ShowScreens(int num_screens)
{
// make all collapse
for (int i = 0; i < SCREEN_MAX; i++)
VisibleScreen[i] = Visibility.Collapsed;
// show only X num screens
for (int i = 0; i < num_screens; i++)
VisibleScreen[i] = Visibility.Visible;
RaisePropertyChanged("VisibleScreen");
}
public void ChangeScreen(int idx)
{
switch (idx)
{
case 0: ScreenRows = 1; ScreenCols = 1; ShowScreens(1); break;
case 1: ScreenRows = 1; ScreenCols = 2; ShowScreens(2); break;
case 2: ScreenRows = 2; ScreenCols = 2; ShowScreens(4); break;
case 3: ScreenRows = 2; ScreenCols = 3; ShowScreens(6); break;
}
}
}
The ScreenView.xaml
<UserControl...>
<!-- SOME HOW IT IS THIS DATACONTEXT CODE MESS UP THE UI -->
<UserControl.DataContext>
<local:ScreenViewModel x:Name="vm"/>
</UserControl.DataContext>
<StackPanel>
<TextBlock>TEST</TextBlock>
</StackPanel>
</UserControl>
Sample Output
As you can see from sample output, my combo selection is 1, so it should display 1 TEST, while 1 square is showing which is correct. But why should it show me 6 TEST? How to make it display 1 TEST?
Here's a corect output
Thanks!

Initial value of selectedIndex is 0 (default value of int field). But content of VisibleScreen array is not matching selectedIndex - you need to call ChangeScreen during initialization, e.g. like this:
public MainWindowViewModel()
{
SelectedIndex = 0;
}
Btw,Grid.Row and Grid.Column have no effect in UniformGrid. UniformGrid arranges items in the order they are added
Don't set DataContext inside UserControls.
instead of Visibility[] create collection of ScreenViewModel of in MainWindowViewModel (ObservableCollection<ScreenViewModel>).
Add bool IsVisible property in ScreenViewModel.
Change ShowScreens method like this:
private void ShowScreens(int num_screens)
{
for (int i = 0; i < SCREEN_MAX; i++)
VisibleScreen[i].IsVisible = i < num_screens ? Visibility.Visible : Visibility.Collapsed;
}
Change the view:
<ItemsControl ItemsSource="{Binding VisibleScreen}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Rows="{Binding ScreenRows}" Columns="{Binding ScreenCols}"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<local:ScreenView Visibility="{Binding IsVisible}"/>
</ItemsControl.ItemTemplate>
</ItemsControl>
ItemTemplate will create a local:ScreenView for each item in VisibleScreen collection AND assign it to DataContext of local:ScreenView

Related

How Can I Access to The Controls in DataTemplate in ListBox in WPF

I have a ListBox including an ItemTemplate with a StackPanel. I want to access that stackpanel and change its visibility.
(Change it's visibility to collapsed when I click mouseleftbutton "closeAll")
I can do that with FindDescendantByName Method but it works for only listbox items on screen (Only first 10 items) but when I am scrolling down, I see that this is not working for other listbox items.
I think that errors occurs because of VisualTreeHelper. What can I use instead of VisualTreeHelper?
Thanks..
XAML CODE
<ListBox x:Name="listBoxEditPast" SelectionMode="Single" Margin="0" Background="#272B34" ScrollViewer.VerticalScrollBarVisibility="Visible">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Border Grid.Row="0" BorderThickness="4,0,0,0" Margin="2,0,0,0" Height="29" Background="#2E323B" Width="1050" BorderBrush="#1373A9" MouseLeftButtonDown="Border_MouseLeftButtonDown">
<DockPanel Name="dockPanelPast" Margin="0,4,0,0">
<Image Name="imgArrow" Source="images/down-arrow.png" HorizontalAlignment="Left" Width="20" Height="18"/>
<TextBlock Text="{Binding CreateDate}" Name="txtTarih" Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="16"/>
<TextBlock Text="{Binding SarjNo}" Name="txtSarjNo" Foreground="#FF9CA518" HorizontalAlignment="Stretch" VerticalAlignment="Center" FontSize="16" Margin="50,0,0,0" Width="90"/>
<TextBlock Text="{Binding Adi}" Name="txtReceteAdi" Foreground="#FF26A053" VerticalAlignment="Center" FontSize="16" Margin="40,0,0,0" HorizontalAlignment="Stretch"/>
<Button Content="Detaylar" Style="{StaticResource BlueButton}" HorizontalAlignment="Right" VerticalAlignment="Center" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" DockPanel.Dock="Right"/>
</DockPanel>
</Border>
<StackPanel Grid.Row="1" Name="stackPanelDetay" Tag="{Binding ID}">
<DockPanel>
<TextBlock Text="Sipariş No" Foreground="#D9480F" VerticalAlignment="Center" />
<TextBlock Text="Parça" Foreground="#AF0FD9" VerticalAlignment="Center" Margin="50,0,0,0" Width="200" />
<TextBlock Text="Malzeme" Foreground="White" VerticalAlignment="Center" Margin="150,0,0,0" Width="90"/>
<TextBlock Text="Müşteri" Foreground="#AF0FD9" VerticalAlignment="Center" Margin="70,0,0,0" />
</DockPanel>
<DockPanel>
<TextBlock Text="{Binding ID}" Foreground="White" VerticalAlignment="Center" Width="100"/>
<TextBlock Text="{Binding ParcaKoduAdi}" Foreground="White" VerticalAlignment="Center" Margin="5,0,0,0" Width="200" />
<TextBlock Text="{Binding Malzeme}" Foreground="White" VerticalAlignment="Center" Margin="152,0,0,0" Width="90" />
<TextBlock Text="{Binding MusteriKoduAdi}" Foreground="White" VerticalAlignment="Center" Margin="70,0,0,0" />
</DockPanel>
</StackPanel>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
C# CODE
public static class FrameworkElementExtensions
{
public static FrameworkElement FindDescendantByName(this FrameworkElement element, string name)
{
if (element == null || string.IsNullOrWhiteSpace(name)) { return null; }
if (name.Equals(element.Name, StringComparison.OrdinalIgnoreCase))
{
return element;
}
var childCount = VisualTreeHelper.GetChildrenCount(element);
for (int i = 0; i < childCount; i++)
{
var result = (VisualTreeHelper.GetChild(element, i) as FrameworkElement).FindDescendantByName(name);
if (result != null) { return result; }
}
return null;
}
}
private void closeAll_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
// StackPanel panel = LayoutHelper.FindElement(listBoxEditPast, n => n.GetType() == typeof(StackPanel)) as StackPanel;
for (int i = 0; i < listBoxEditPast.Items.Count; i++)
{
var element = listBoxEditPast.ItemContainerGenerator.ContainerFromIndex(i) as FrameworkElement;
if (element != null)
{
var sp = element.FindDescendantByName("stackPanelDetay") as StackPanel;
if (sp != null)
{
sp.Visibility = Visibility.Collapsed;
}
}
}
}
noting to do with the visualtreehelper, this is because the list is virtualized, so only the first ten items are created and then replaced by the ten next....and you loose your modifications
you must not work with the element in the data template by code
iterate through your data to set a boolean to true/false for all and then change the stack and bind the visibility to this boolean
<StackPanel Grid.Row="1" Name="stackPanelDetay" Visibility="{Binding myBoolean, Converter=BoolToVisibility}">

Photo and description on Flipview

I have a flipview which contains photos and descriptions. I want when photo1 be tapped, then descbox1 not visible. And if photo1 be tapped again, then descbox1 will appear.
XAML:
<FlipView x:Name="narrowFlipview"
ItemsSource="{Binding Group.Items}"
SelectedItem="{Binding Item, Mode=TwoWay}"
Foreground="{x:Null}"
Visibility="Collapsed">
<FlipView.ItemTemplate>
<DataTemplate>
<Grid x:Name="content1"
Margin="0,0,0,0">
<Image x:Name="photo1"
Margin="0,0,10,10"
Source="{Binding ImagePath}"
Tapped="photo_Tapped" />
<Grid x:Name="detail"
VerticalAlignment="Bottom"
Height="200">
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Button x:Name="hideBtn"
Height="50"
Width="50"
Margin="0,0,5,0"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Grid.Row="0"
Click="hideBtn_Click">
<Button.Background>
<ImageBrush Stretch="Uniform"
ImageSource="images/media/ikon-56-app-white-down.png" />
</Button.Background>
</Button>
<Button x:Name="detailBtn"
Height="50"
Width="50"
Margin="0,0,5,0"
HorizontalAlignment="Right"
VerticalContentAlignment="Bottom"
Grid.Row="1"
Visibility="Collapsed"
Click="detailBtn_Click">
<Button.Background>
<ImageBrush Stretch="Uniform"
ImageSource="images/media/ikon-56-app-white-up.png" />
</Button.Background>
</Button>
<ScrollViewer x:Name="descBox1"
Grid.Row="1"
Height="150"
Background="#95000000"
VerticalScrollBarVisibility="Auto">
<TextBlock x:Name="descriptionText1"
Text="{Binding Description}"
Margin="20,20,20,0"
TextWrapping="Wrap"
TextAlignment="Justify"
VerticalAlignment="Top"
Height="auto"
Foreground="White"
FontSize="21" />
</ScrollViewer>
</Grid>
</Grid>
</DataTemplate>
</FlipView.ItemTemplate>
</FlipView>
I tried using the code below:
private DependencyObject FindChildControl<T>(DependencyObject control, string ctrlName)
{
int childNumber = VisualTreeHelper.GetChildrenCount(control);
for (int i = 0; i < childNumber; i++)
{
DependencyObject child = VisualTreeHelper.GetChild(control, i);
FrameworkElement fe = child as FrameworkElement;
// Not a framework element or is null
if (fe == null) return null;
if (child is T && fe.Name == ctrlName)
{
// Found the control so return
return child;
}
else
{
// Not found it - search children
DependencyObject nextLevel = FindChildControl<T>(child, ctrlName);
if (nextLevel != null)
return nextLevel;
}
}
return null;
}
public bool _IsOn;
public bool IsOn
{
get
{
return _IsOn;
}
set
{
_IsOn = value;
}
}
private void photo_Tapped(object sender, TappedRoutedEventArgs e)
{
ScrollViewer descBox1 = FindChildControl<ScrollViewer>(this, "descBox1") as ScrollViewer;
Button hideBtn = FindChildControl<Button>(this, "hideBtn") as Button;
Button detailBtn = FindChildControl<Button>(this, "detaiBtn") as Button;
IsOn = !IsOn;
if (_IsOn)
{
descBox1.Visibility = Visibility.Collapsed;
hideBtn.Visibility = Visibility.Collapsed;
detailBtn.Visibility = Visibility.Visible;
}
else
{
descBox1.Visibility = Visibility.Visible;
hideBtn.Visibility = Visibility.Visible;
detailBtn.Visibility = Visibility.Collapsed;
}
}
But when I tap photo1, descBox1 would not collapse, hiddenBtn would not collapsed, detailBtn would not visible.
How to handle it?
According to your requirement, I'd think using Binding here to control these control's visibility would be a simpler solution. For example, we can take advantage of the Tag property.
Ref Remarks in FrameworkElement.Tag property:
The scenario for the Tag property is to provide an general-purpose property on all FrameworkElement classes that supports data binding, animation and styles for itself but where the property's value does not have any implicit meaning to platform subsystems like layout, app model, text, input and so on.
Here we can use this property to store the Visibility and in other controls, bind ther Visibility property to this property like:
<ScrollViewer x:Name="descBox1"
Grid.Row="1"
Height="150"
Background="#95000000"
VerticalScrollBarVisibility="Auto"
Visibility="{Binding Tag, ElementName=photo1}">
<TextBlock x:Name="descriptionText1"
Height="auto"
Margin="20,20,20,0"
VerticalAlignment="Top"
FontSize="21"
Foreground="White"
Text="{Binding Description}"
TextAlignment="Justify"
TextWrapping="Wrap" />
</ScrollViewer>
Then in photo_Tapped method, we can change Tag's value to control the visibility of "descBox1".
private void photo_Tapped(object sender, TappedRoutedEventArgs e)
{
var tag = (sender as Image)?.Tag?.ToString();
//if we didn't set Tag in Image, its value should be null and descBox1 will be Visible
if (string.IsNullOrEmpty(tag) || tag.Equals("Visible"))
{
(sender as Image).Tag = Visibility.Collapsed;
}
else
{
(sender as Image).Tag = Visibility.Visible;
}
}
"hiddenBtn" is similar, we only need to set the Mode of the Binding to TwoMay, so that when we change its visibility, "descBox1" and "detailBtn" will also change their visibility automatically.
<Button x:Name="hideBtn"
Grid.Row="0"
Width="50"
Height="50"
Margin="0,0,5,0"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Click="hideBtn_Click"
Visibility="{Binding Tag, ElementName=photo1, Mode=TwoWay}">
<Button.Background>
<ImageBrush ImageSource="images/media/ikon-56-app-white-down.png" Stretch="Uniform" />
</Button.Background>
</Button>
private void hideBtn_Click(object sender, RoutedEventArgs e)
{
ChangeButtonVisibility(sender);
}
private void ChangeButtonVisibility(object sender)
{
var visibility = (sender as Button)?.Visibility;
if (visibility.Equals(Visibility.Visible))
{
(sender as Button).Visibility = Visibility.Collapsed;
}
else
{
(sender as Button).Visibility = Visibility.Visible;
}
}
"detailBtn" is the same as "hiddenBtn", but its visibility is opposite to "hiddenBtn". So we will need a InvertedVisibilityConverter like following:
public class InvertedVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
return InvertedVisibility(value);
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
return InvertedVisibility(value);
}
private object InvertedVisibility(object value)
{
var visibility = value?.ToString();
if (string.IsNullOrEmpty(visibility) || visibility.Equals("Visible"))
{
return Visibility.Collapsed;
}
else
{
return Visibility.Visible;
}
}
}
And in "detailBtn", setting Binding like following:
<Button x:Name="detailBtn"
Grid.Row="1"
Width="50"
Height="50"
Margin="0,0,5,0"
HorizontalAlignment="Right"
VerticalContentAlignment="Bottom"
Click="detailBtn_Click"
Visibility="{Binding Tag, ElementName=photo1, Mode=TwoWay, Converter={StaticResource InvertedVisibilityConverter}}">
<Button.Background>
<ImageBrush ImageSource="images/media/ikon-56-app-white-up.png" Stretch="Uniform" />
</Button.Background>
</Button>
private void detailBtn_Click(object sender, RoutedEventArgs e)
{
ChangeButtonVisibility(sender);
}
Update: To make the visibilities in all FlipViewItems have the same behavior, we need a dependence property that can store the visibility "globally". So we can use FlipView's Tag property instead of Image's Tag property and in Image set the Binding like following:
<Image x:Name="photo1"
Margin="0,0,10,10"
Source="{Binding ImagePath}"
Tag="{Binding Tag, ElementName=narrowFlipview, Mode=TwoWay}"
Tapped="photo_Tapped" />
After this all Image's Tag will have the same value. And as this is a two-way binding, when we change one Image's Tag value, it will automatically change FlipView.Tag's value and then propagate to all other Images.
In other controls like "descBox1", "hiddenBtn" and "detailBtn", we can also change their Binding by change ElementName from photo1 to narrowFlipview. Using "detailBtn" for example:
<Button x:Name="detailBtn"
Grid.Row="1"
Width="50"
Height="50"
Margin="0,0,5,0"
HorizontalAlignment="Right"
VerticalContentAlignment="Bottom"
Click="detailBtn_Click"
Visibility="{Binding Tag, ElementName=narrowFlipview, Mode=TwoWay, Converter={StaticResource InvertedVisibilityConverter}}">
<Button.Background>
<ImageBrush ImageSource="images/media/ikon-56-app-white-up.png" Stretch="Uniform" />
</Button.Background>
</Button>
And there is no need to change the code-behind, after editing the Bindings in XAML, it should be able to achieve what you want.

ListBox ScrollIntoView not working OnNavigatedTo

I'm making a timer with adjustable time. For that reason I want to set the time using listboxes (one for minutes and one for seconds). The filling of the listboxes is accomplished using the following code.
public EditTime()
{
this.InitializeComponent();
List<Numbers> numbers = new List<Numbers>();
for (int i = 0; i < 61; i++)
{
numbers.Add(new Numbers() { Number = i });
}
listBoxobjM.ItemsSource = numbers;
listBoxobjS.ItemsSource = numbers;
this.navigationHelper = new NavigationHelper(this);
this.navigationHelper.LoadState += this.NavigationHelper_LoadState;
this.navigationHelper.SaveState += this.NavigationHelper_SaveState;
}
public class Numbers
{
public int Number { get; set; }
}
In XAML I have the following code for the ListBoxes:
<Grid Grid.Row="1" x:Name="ContentRootM" Margin="65,0,0,0" Width="130">
<ListBox Background="Transparent" Margin="10,10,10,10" BorderThickness="2" MaxHeight="580" Grid.Row="2" x:Name="listBoxobjM" VerticalContentAlignment="Top" HorizontalContentAlignment="Center">
<ListBox.ItemTemplate>
<DataTemplate>
<Border Margin="5" BorderBrush="{ThemeResource ApplicationHeaderForegroundThemeBrush}" BorderThickness="1" Background="{ThemeResource ButtonBackgroundThemeBrush}">
<TextBlock TextAlignment="Left" HorizontalAlignment="Left" Width="70" Height="80" x:Name="LbM" Text="{Binding Number}" FontSize="48" Foreground="{ThemeResource ButtonForegroundThemeBrush}" />
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
<Grid Grid.Row="1" x:Name="ContentRootS" Margin="10,0,0,0" Width="130">
<ListBox Background="Transparent" Margin="10,10,10,10" Height="auto" BorderThickness="2" MaxHeight="580" Grid.Row="2" x:Name="listBoxobjS" VerticalContentAlignment="Top" HorizontalContentAlignment="Center">
<ListBox.ItemTemplate>
<DataTemplate>
<Border Margin="5" BorderBrush="{ThemeResource ApplicationHeaderForegroundThemeBrush}" BorderThickness="1" Background="{ThemeResource ButtonBackgroundThemeBrush}">
<StackPanel Width="125" Orientation="Horizontal" Grid.Row="1">
<TextBlock TextAlignment="Left" HorizontalAlignment="Left" Width="70" Height="80" x:Name="LbS" Text="{Binding Number}" TextWrapping="Wrap" FontSize="48" Foreground="{ThemeResource ButtonForegroundThemeBrush}" />
</StackPanel>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
When I navigate to this page I can select the preselected time (minutes and seconds) using listBoxobjM.SelectedIndex = i; in the following code. I can scroll manually to this Item and see it is selected.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
this.navigationHelper.OnNavigatedTo(e);
string parameter = e.Parameter as string;
string[] parts = parameter.Split(';');
id = int.Parse(parts[0]);
....
DatabaseHelper fetch = new DatabaseHelper();
TeamType team = fetch.GetTeamType(id);
for (int i = 0; i < 60; i++)
{
if (i == team.PlayTime.Minutes)
{
listBoxobjM.SelectedIndex = i;
listBoxobjM.ScrollIntoView(listBoxobjM.SelectedIndex);
}
if (i == team.PlayTime.Seconds)
{
listBoxobjS.SelectedIndex = i;
listBoxobjS.ScrollIntoView(listBoxobjS.SelectedIndex);
}
}
}
I want the Listbox automatically to scroll to the SelectedIndex, but instead the Listbox shows the first Items on top. How can I take care theListBox scrolls to the SelectedIndex?
ListBox.ScrollIntoView() takes an item that's in the ListBox, not an index. (MSDN documentation) So instead of
listBoxobjM.ScrollIntoView(listBoxobjM.SelectedIndex);
try
listBoxobjM.ScrollIntoView(listBoxobjM.SelectedItem);
instead.
Eventually I found the solution myself via an other Stack Overflow question. Here they also had problems with the ListView because it was filled with a delay. Using a await Task.Delay (see code) the problem is solved. I thank everybody for his contribution.
for (int i = 0; i < 60; i++)
{
if (i == team.PlayTime.Minutes)
{
listBoxobjM.SelectedIndex = i;
await Task.Delay(1000);
listBoxobjM.ScrollIntoView(listBoxobjM.SelectedItem);
}
if (i == team.PlayTime.Seconds)
{
listBoxobjS.SelectedIndex = i;
await Task.Delay(1000);
listBoxobjS.ScrollIntoView(listBoxobjS.SelectedItem);
}
}

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="{...}"

Gidview item not updating

My page having city listing and searching functionality. When page first time loading, it is showing all record.
When user enter search Text and tap on search button. it is not updating gridview list. I check by placing debug point my code is working fine. but gridview list not showing updated list.
Following is my code.
XAML:
<StackPanel VerticalAlignment="Top">
<TextBlock Style="{StaticResource ListTextBlockStyle}" FontWeight="Bold" Text="{Binding Description}" />
<TextBlock Style="{StaticResource ListTextBlockStyle}" Text="{Binding Description}" />
</StackPanel>
<TextBlock Style="{StaticResource DistanceTextBlockStyle}" TextWrapping="Wrap" Text="XXXm" />
<Image Width="10" VerticalAlignment="Center" Source="ms-appx:///Assets/arrowright.png"/>
</StackPanel>
<Rectangle Height="1" Stroke="Black" StrokeThickness="0.5" Margin="0,3,0,0" />
</StackPanel>
</Border>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
<Border Grid.Row="1" Height="60" VerticalAlignment="Bottom">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<TextBox x:Name="txtSearch" Margin="0,0,10,0" TextWrapping="Wrap" PlaceholderText="Search" VerticalAlignment="Center" Width="300" Height="50" />
<Image x:Name="imgSearch" Height="50" Width="50" Source="ms-appx:///Assets/btnSearch.png" Tapped="imgSearch_Tapped"/>
</StackPanel>
</StackPanel>
</Border>
C#:
public List<City> gs_CityList = new List<City>();
protected override void OnNavigatedTo(NavigationEventArgs e)
{
fillCityList();
}
private void fillCityList()
{
gs_CityList.Clear();
if (string.IsNullOrEmpty(CityListManagerManager.ms_searchTxt))
{
foreach (City foCity in CityListManagerManager.ms_CityList)
{
City loCity = new City();
loCity.Description = foCity.Description.Replace("\n", "").Substring(0, 15) + "...";
loCity.longtitude = foCity.longtitude;
loCity.latitude = foCity.latitude;
loCity.Location = foCity.Location;
gs_CityList.Add(loCity);
}
}
else
{
foreach (City foCity in CityListManagerManager.ms_CityList.Where(p => p.Description.ToLower().Contains(CityListManagerManager.ms_searchTxt.ToLower())))
{
City loCity = new City();
loCity.Description = foCity.Description.Replace("\n", "").Substring(0, 15) + "...";
loCity.longtitude = foCity.longtitude;
loCity.latitude = foCity.latitude;
loCity.Location = foCity.Location;
gs_CityList.Add(loAEDPin);
}
txtSearch.Text = CityListManagerManager.ms_searchTxt;
}
if (gs_CityList.Count > 0)
{
gvCityList.DataContext = gs_CityList; // --- This binding data to gridview
}
else
MessageBox("City not found...!");
}
private void imgSearch_Tapped(object sender, TappedRoutedEventArgs e)
{
CityListManagerManager.ms_searchTxt = txtSearch.Text.Trim();
fillCityList();
}
You should try changing your List<City> into an ObservableCollection<City>, as this allows the binding to get notified about changes.
You could also think about using a CollectionViewSource as data source for the GridView and modifying its Filter property instead of re-filling the collection.

Categories

Resources