user3239349
user3239349

Reputation: 917

C# UWP Listview/GridView mark of selected item

I am creating UWP app, and I maked external arrow "marker" of selected item in listview...

Like this:enter image description here

I have managed to achieve this with next code:

var current = lvMain.Items.FirstOrDefault(a => (a as MyModel).Selected) as MyModel;
ListViewItem selected = lvMain.ContainerFromItem(current) as ListViewItem;    
GeneralTransform generalTransform1 = gvEpg.TransformToVisual(selected);
Point currentPoint = generalTransform1.TransformPoint(new Point());

In Scroll change event I am calling this and set the arrow position by the Point of my item. And this is working.

But, I want to simplified this. Is there any kind of binding or something like that, that would make arrow always follow the item?

Upvotes: 2

Views: 996

Answers (1)

Jet  Chopper
Jet Chopper

Reputation: 1488

Here's the sample.

XAML MainPage:

<Page.Resources>
    <DataTemplate x:Key="DataTemplate">
        <Canvas Height="80" Width="200">
            <TextBlock Text="{Binding}"/>
        </Canvas>
    </DataTemplate>
</Page.Resources>

<StackPanel Orientation="Horizontal">
    <ListView x:Name="ListView" Width="400"
              SelectionChanged="ListView_OnSelectionChanged"
              ItemTemplate="{StaticResource DataTemplate}"/>

    <Canvas x:Name="ParentCanvas">
        <Image x:Name="Arrow" 
               Stretch="UniformToFill" Width="200" Height="80" 
               Source="Assets/Red_Left_Arrow.png"/>
    </Canvas>
</StackPanel>

Code behind:

    private readonly List<string> _names = new List<string>();
    private Visual _rectangleVisual;
    private Visual _parentVisual;

    public MainPage()
    {
        InitializeComponent();
        Loaded += MainPage_Loaded;
    }

    private void MainPage_Loaded(object sender, RoutedEventArgs e)
    {
        for (int i = 0; i < 32; i++)
        {
            _names.Add("item " + i);
        }

        ListView.ItemsSource = _names;

        _parentVisual = ElementCompositionPreview.GetElementVisual(ParentCanvas);
        _rectangleVisual = ElementCompositionPreview.GetElementVisual(Arrow);

        var border = VisualTreeHelper.GetChild(ListView, 0) as Border;
        var scrollViewer = border.Child as ScrollViewer;

        var scrollerProperties = ElementCompositionPreview.GetScrollViewerManipulationPropertySet(scrollViewer);

        var offsetExpressionAnimation = _rectangleVisual.Compositor.CreateExpressionAnimation("Scroller.Translation.Y");
        offsetExpressionAnimation.SetReferenceParameter("Scroller", scrollerProperties);

        _rectangleVisual.StartAnimation("Offset.Y", offsetExpressionAnimation);
    }

    private void ListView_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        var listViewItem = ListView.ContainerFromItem(ListView.SelectedItem) as ListViewItem;
        var listItemVisual = ElementCompositionPreview.GetElementVisual(listViewItem);

        _parentVisual.Offset = new Vector3(_parentVisual.Offset.X, listItemVisual.Offset.Y, 0);
    }

Looks like what you asked for:

enter image description here

Upvotes: 3

Related Questions