detailCode
detailCode

Reputation: 537

Refresh SemanticZoom ObservableCollection in ViewModel

When using a SemanticZoom control, is there a way to update the ObservableCollection in the ViewModel after a table change? After making changes to the table in SQLite, within the same page (categories.xaml.cs), the SemanticZoom control does not update. Reloading the page from menu navigation does reload the page with the correct data. If the control just took an ObservableCollection as it's items source, the ObservableCollection could just be refreshed. Using a ViewModel was the only code example I could find for the SemanticZoom control. Thanks in advance!

categories.xaml

<Page.DataContext>
    <vm:CategoriesViewModel></vm:CategoriesViewModel>
</Page.DataContext>
<Page.Resources>
    <CollectionViewSource  x:Name="Collection" IsSourceGrouped="true" ItemsPath="Items" Source="{Binding CategoryGroups}" />
</Page.Resources>

<SemanticZoom Name="szCategories" ScrollViewer.ZoomMode="Enabled">
    <SemanticZoom.ZoomedOutView>
        <GridView ScrollViewer.IsHorizontalScrollChainingEnabled="False">
            <GridView.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Group.Name }" Foreground="Gray" Margin="5" FontSize="25" />
                </DataTemplate>
            </GridView.ItemTemplate>
        </GridView>
    </SemanticZoom.ZoomedOutView>
    <SemanticZoom.ZoomedInView>
        <ListView Name="lvCategories" ItemsSource="{Binding Source={StaticResource Collection}}" Tapped="lvCategories_Tapped">
            <ListView.ItemTemplate>
                <DataTemplate x:DataType="data:Category">
                    <StackPanel>
                        <TextBlock Text="{Binding Title}" Margin="5" />
                    </StackPanel>
                </DataTemplate>
            </ListView.ItemTemplate>
            <ListView.GroupStyle>
                <GroupStyle>
                    <GroupStyle.HeaderTemplate>
                        <DataTemplate>
                            <StackPanel Orientation="Vertical">
                                <TextBlock Text='{Binding Name}' Foreground="Gray" FontSize="25" Margin="5,5,5,0" />
                            </StackPanel>
                        </DataTemplate>
                    </GroupStyle.HeaderTemplate>
                </GroupStyle>
            </ListView.GroupStyle>
        </ListView>
    </SemanticZoom.ZoomedInView>
</SemanticZoom>

categories.xaml.cs

    public Categories()
    {
        this.InitializeComponent();

        var collectionGroups = Collection.View.CollectionGroups;
        ((ListViewBase)this.szCategories.ZoomedOutView).ItemsSource = collectionGroups;
    }

CategoriesViewModel.cs

internal class CategoriesViewModel : BindableBase
{
    public CategoriesViewModel()
    {
        CategoryGroups = new ObservableCollection<CategoryDataGroup>(CategoryDataGenerator.GetGroupedData());
    }

    private ObservableCollection<CategoryDataGroup> _groups;
    public ObservableCollection<CategoryDataGroup> CategoryGroups
    {
        get { return _groups; }
        set { SetProperty(ref _groups, value); }
    }
}

public abstract class BindableBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
    {
        if (object.Equals(storage, value)) return false;

        storage = value;
        this.OnPropertyChanged(propertyName);

        return true;
    }
    protected void OnPropertyChanged(string propertyName)
    {
        var eventHandler = this.PropertyChanged;
        if (eventHandler != null)
        {
            eventHandler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

SymanticZoom.cs

internal class CategoryDataGroup
{
    public string Name { get; set; }

    public List<CategoryData> Items { get; set; }
}

internal class CategoryData
{
    public CategoryData(string grp, string title)
    {
        Grp = grp;
        Title = title;
    }

    public string Grp { get; private set; }
    public string Title { get; private set; }
}

internal class CategoryDataGenerator
{
    private static List<CategoryData> _data;

    public static List<CategoryDataGroup> GetGroupedData()
    {
        if (_data != null)
            _data.Clear();
        GenerateData();

        return _data.GroupBy(d => d.Grp[0],
            (key, items) => new CategoryDataGroup() { Name = key.ToString(), Items = items.ToList() }).ToList();
    }

    private static void GenerateData()
    {
        ObservableCollection<Category> ocCategories = new ObservableCollection<Category>();
        SQLiteManager.Categories.Select(ocCategories);

        _data = new List<CategoryData>();
        foreach (var temp in ocCategories)
        {
            _data.Add(new CategoryData(temp.Name.Substring(0,1), temp.Name));
        }            
    }
}

Upvotes: 0

Views: 190

Answers (1)

Jayden
Jayden

Reputation: 3286

The zoomed-in view and zoomed-out view should be synchronized, so if a user selects a group in the zoomed-out view, the details of that same group are shown in the zoomed-in view. You can use a CollectionViewSource or add code to synchronize the views.

For more info, see Semantic zoom.

We can use CollectionViewSource control in our page, it provides a data source that adds grouping and current-item support to collection classes. Then we can bind the GridView.ItemSource and ListView.ItemSource to the CollectionViewSource. When we set new data to the CollectionViewSource, the GridView in SemanticZoom.ZoomedOutView and ListView in SemanticZoom.ZoomedInView will be updated.

xmlns:wuxdata="using:Windows.UI.Xaml.Data">

<Page.Resources>
    <CollectionViewSource x:Name="ContactsCVS"  IsSourceGrouped="True" />
    <DataTemplate x:Key="ZoomedInTemplate" x:DataType="data:Contact">
        <StackPanel Margin="20,0,0,0">
            <TextBlock Text="{x:Bind Name}" />
            <TextBlock Text="{x:Bind Position}" TextWrapping="Wrap" HorizontalAlignment="Left" Width="300" />
        </StackPanel>
    </DataTemplate>
    <DataTemplate x:Key="ZoomedInGroupHeaderTemplate" x:DataType="data:GroupInfoList">
        <TextBlock Text="{x:Bind Key}"/>
    </DataTemplate>
    <DataTemplate x:Key="ZoomedOutTemplate" x:DataType="wuxdata:ICollectionViewGroup">
        <TextBlock Text="{x:Bind Group.(data:GroupInfoList.Key)}" TextWrapping="Wrap"/>
    </DataTemplate>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <StackPanel>
        <SemanticZoom x:Name="Control1" Height="500">
            <SemanticZoom.ZoomedInView>
                <GridView ItemsSource="{x:Bind ContactsCVS.View,Mode=OneWay}" ScrollViewer.IsHorizontalScrollChainingEnabled="False" SelectionMode="None" 
                ItemTemplate="{StaticResource ZoomedInTemplate}">
                    <GridView.GroupStyle>
                        <GroupStyle HeaderTemplate="{StaticResource ZoomedInGroupHeaderTemplate}" />
                    </GridView.GroupStyle>
                </GridView>
            </SemanticZoom.ZoomedInView>
            <SemanticZoom.ZoomedOutView>
                <ListView ItemsSource="{x:Bind ContactsCVS.View.CollectionGroups}" SelectionMode="None" ItemTemplate="{StaticResource ZoomedOutTemplate}" />
            </SemanticZoom.ZoomedOutView>
        </SemanticZoom>
    </StackPanel>
</Grid>

Upvotes: 0

Related Questions