也是以前寫的控件了,模仿NetFlix的河的設計。git
大致要求以下:github
1. 橫向的ListViewapp
2. 左右按鈕,能夠左右移動河卡片,左右的滾動條不可見佈局
3. 左右按鈕僅在鼠標Hover事件中可見spa
你們能夠看下NetFlix uwp版,國內愛奇藝也是這樣設計的,芒果TV以前是,可是新版去掉了這種風格。設計
其實我也是一個菜鳥,一開始糾結怎麼寫這個控件,怎麼傳遞ItemsSource,並且還在SO上發起了提問雙向綁定
很遺憾,uwp幾乎滅絕,沒有人回答個人問題。因而各類尋找,終於發現了大神 Pieter Nijs code
寫的文章https://blog.pieeatingninjas.be/2016/01/17/custom-uwp-control-step-through-listview/blog
大神的需求和個人相似,見圖事件
因而膜拜文章,寫下了適合我本身的控件見圖:
👌好了,下面開始擼代碼,先新建一個用戶控件,名字叫 StepThroughListView ,看看Xaml的佈局,
<Grid> <ListView x:Name="ListViewRiver" HorizontalAlignment="Stretch" SingleSelectionFollowsFocus="True" ScrollViewer.VerticalScrollBarVisibility="Hidden" ScrollViewer.HorizontalScrollBarVisibility="Hidden" ScrollViewer.VerticalScrollMode="Disabled" ScrollViewer.HorizontalScrollMode="Disabled" > <ListView.ItemsPanel> <ItemsPanelTemplate> <VirtualizingStackPanel Orientation="Horizontal"/> </ItemsPanelTemplate> </ListView.ItemsPanel> </ListView> <Button x:Name="ButtonLeft"/> <Button x:Name="ButtonRight" HorizontalAlignment="Right"/> </Grid>
這樣大致建立了一個這樣的橫向的ListView,橙色矩形爲ListView,灰色圓圈是左右按鈕Button,藍色是ListViewItem
按鈕是默認垂直居中
而後咱們須要給ListView賦值ItemsSource、SelectedItem、ItemTemplate,這些須要在C#代碼中使用依賴屬性來完成。
public IEnumerable ItemsSource { get { return (IEnumerable)GetValue(ItemsSourceProperty); } set { SetValue(ItemsSourceProperty, value); RaisePropertyChanged(); } } public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register(nameof(ItemsSource), typeof(IEnumerable), typeof(StepThroughListView), new PropertyMetadata(DependencyProperty.UnsetValue)); public DataTemplate ItemTemplate { get { return (DataTemplate)GetValue(ItemTemplateProperty); } set { SetValue(ItemTemplateProperty, value); RaisePropertyChanged(); } } public static readonly DependencyProperty ItemTemplateProperty = DependencyProperty.Register(nameof(ItemTemplate), typeof(DataTemplate), typeof(StepThroughListView), new PropertyMetadata(DependencyProperty.UnsetValue)); public object SelectedItem { get { return GetValue(SelectedItemProperty); } set { if (SelectedItem != value) { SetValue(SelectedItemProperty, value); RaisePropertyChanged(); } } } public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register(nameof(SelectedItem), typeof(object), typeof(StepThroughListView), new PropertyMetadata(DependencyProperty.UnsetValue));
而後在Xaml中,須要給ListView作雙向綁定,
ItemsSource="{Binding ItemsSource, ElementName=root}" SelectedItem="{x:Bind SelectedItem, Mode=TwoWay}" ItemTemplate="{x:Bind ItemTemplate, Mode=TwoWay}"
接下來就能夠處理左右按鈕的響應事件了,由於橫向的ListView左右滾動事件被咱們禁用了,因此須要手動控制。
首先定義一個私有變量
ScrollViewer _InternalListScrollViewer;
在ListView的Loaded事件中,經過VisualTreeHelper查找🔍ListView內部的ScrollViewer。
private void ListView_Loaded(object sender, RoutedEventArgs e) { _InternalListScrollViewer = TreeHelper.FindVisualChild<ScrollViewer>((DependencyObject)sender); }
public static TChild FindVisualChild<TChild>(DependencyObject obj) where TChild : DependencyObject { if (obj == null) return null; for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++) { DependencyObject child = VisualTreeHelper.GetChild(obj, i); if (child != null && child is TChild found) return found; else { TChild childOfChild = FindVisualChild<TChild>(child); if (childOfChild != null) return childOfChild; } } return null; }
左右按鈕的Tapped事件,左按鈕和右按鈕的的方向正好相反。因此合併一下
private void ButtonRight_Tapped(object sender, TappedRoutedEventArgs e) { ScrollList(shouldScrollDown: true); } private void ButtonLeft_Tapped(object sender, TappedRoutedEventArgs e) { ScrollList(shouldScrollDown: false); } private void ScrollList(bool shouldScrollDown) { SelectedItem = null; var step = Math.Floor(Window.Current.Bounds.Width / 400); if (!shouldScrollDown) step *= -1; //_InternalListScrollViewer.ScrollToVerticalOffset( // _InternalListScrollViewer.VerticalOffset + height); System.Diagnostics.Debug.WriteLine(_InternalListScrollViewer.ScrollableWidth); _InternalListScrollViewer.ChangeView(_InternalListScrollViewer.HorizontalOffset + step, null, null); }
上面的變量step,我用的是根據窗體大小寬度來決定步長。不過你也能夠用本身的一個固定值,好比2。
而後我又加了一個屬性,叫AlwaysShowButton。若是設置Visible,那麼左右按鈕一直可見。
設置爲Collapse的話,只有當鼠標移動到ListView上,纔會顯示左右按鈕。
================================================
好了,囉嗦那麼多,控件的代碼奉上:
https://github.com/hupo376787/StepThroughListView
用法也很簡單:
<ctl:StepThroughListView AlwaysShowButton="Collapsed" ItemsSource="{x:Bind product}" Tapped="StepThroughListView_Tapped"> </ctl:StepThroughListView> private void StepThroughListView_Tapped(object sender, TappedRoutedEventArgs e) { var item = (sender as Controls.StepThroughListView).SelectedItem as ProductItem; if (item != null) { //TODO... } }
OK,下班!!!