最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于WPF實現(xiàn)描點導航功能

 更新時間:2025年06月05日 09:59:05   作者:WPF開發(fā)者  
這篇文章主要為大家詳細介紹了如何基于WPF實現(xiàn)描點導航功能,文中的示例代碼講解詳細,具有一定的借鑒價值,感興趣的小伙伴可以了解一下

WPF 實現(xiàn)描點導航

1.框架支持.NET4 至 .NET8

2.Visual Studio 2022;

有一位開發(fā)者需要實現(xiàn)類似「左側(cè)導航欄 + 右側(cè)滾動內(nèi)容」的控件,需要支持數(shù)據(jù)綁定、內(nèi)容模板、同步滾動定位等功能。

1. 新增 NavScrollPanel.cs

  • 左側(cè)導航欄ListBox:顯示導航,支持點擊定位;
  • 右側(cè)滾動內(nèi)容區(qū) ScrollViewer 和 StackPanel:展示對應內(nèi)容模板,支持滾動自動選中導航項。
  • 通過 ItemsSource 綁定內(nèi)容集合;
  • 自定義 ItemTemplate 顯示內(nèi)容;
  • 通過 TranslatePoint 方法,可以獲取元素相對于容器的坐標位置,并確保該位置不受 Margin 的影響。通過調(diào)用 ScrollToVerticalOffset 來滾動右側(cè)容器;
public classNavScrollPanel : Control
{
    static NavScrollPanel()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(NavScrollPanel),
            new FrameworkPropertyMetadata(typeof(NavScrollPanel)));
    }

    public IEnumerable ItemsSource
    {
        get => (IEnumerable)GetValue(ItemsSourceProperty);
        set => SetValue(ItemsSourceProperty, value);
    }

    publicstaticreadonly DependencyProperty ItemsSourceProperty =
        DependencyProperty.Register(nameof(ItemsSource), typeof(IEnumerable), typeof(NavScrollPanel), new PropertyMetadata(null, OnItemsSourceChanged));

    public DataTemplate ItemTemplate
    {
        get => (DataTemplate)GetValue(ItemTemplateProperty);
        set => SetValue(ItemTemplateProperty, value);
    }

    publicstaticreadonly DependencyProperty ItemTemplateProperty =
        DependencyProperty.Register(nameof(ItemTemplate), typeof(DataTemplate), typeof(NavScrollPanel), new PropertyMetadata(null));

    publicint SelectedIndex
    {
        get => (int)GetValue(SelectedIndexProperty);
        set => SetValue(SelectedIndexProperty, value);
    }

    publicstaticreadonly DependencyProperty SelectedIndexProperty =
        DependencyProperty.Register(nameof(SelectedIndex), typeof(int), typeof(NavScrollPanel), new PropertyMetadata(-1, OnSelectedIndexChanged));

    private ListBox _navListBox;
    private ScrollViewer _scrollViewer;
    private StackPanel _contentPanel;

    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();

        _navListBox = GetTemplateChild("PART_ListBox") as ListBox;
        _scrollViewer = GetTemplateChild("PART_ScrollViewer") as ScrollViewer;
        _contentPanel = GetTemplateChild("PART_ContentPanel") as StackPanel;

        if (_navListBox != null)
        {
            _navListBox.DisplayMemberPath = "Title";
            _navListBox.SelectionChanged -= NavListBox_SelectionChanged;
            _navListBox.SelectionChanged += NavListBox_SelectionChanged;
        }
        if (_scrollViewer != null)
        {
            _scrollViewer.ScrollChanged += ScrollViewer_ScrollChanged;
        }
        RenderContent();
    }

    private void NavListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        SelectedIndex = _navListBox.SelectedIndex;
    }

    private void ScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
    {
        double currentOffset = _scrollViewer.VerticalOffset;                                    
        double viewportHeight = _scrollViewer.ViewportHeight;                                  

        for (int i = 0; i < _contentPanel.Children.Count; i++)
        {
            var element = _contentPanel.Children[i] as FrameworkElement;
            if (element == null) continue;

            Point relativePoint = element.TranslatePoint(new Point(0, 0), _contentPanel);

            if (relativePoint.Y >= currentOffset && relativePoint.Y < currentOffset + viewportHeight)
            {
                _navListBox.SelectionChanged -= NavListBox_SelectionChanged;
                SelectedIndex = i;
                _navListBox.SelectionChanged += NavListBox_SelectionChanged;
                break;
            }
        }
    }


    private static void OnItemsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (d is NavScrollPanel control)
        {
            control.RenderContent();
        }
    }

    private static void OnSelectedIndexChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (d is NavScrollPanel control)
        {
            int index = (int)e.NewValue;

            if (control._contentPanel != null &&
                index >= 0 && index < control._contentPanel.Children.Count)
            {
                var target = control._contentPanel.Children[index] as FrameworkElement;
                if (target != null)
                {
                    var virtualPoint = target.TranslatePoint(new Point(0, 0), control._contentPanel);
                    control._scrollViewer.ScrollToVerticalOffset(virtualPoint.Y);
                }
            }
        }
    }

    private void RenderContent()
    {
        if (_contentPanel == null || ItemsSource == null || ItemTemplate == null)
            return;
        _contentPanel.Children.Clear();
        foreach (var item in ItemsSource)
        {
            var content = new ContentControl
            {
                Content = item,
                ContentTemplate = ItemTemplate,
                Margin = new Thickness(10,50,10,50)
            };
            _contentPanel.Children.Add(content);
        }
    }
}

2. 新增 NavScrollPanel.Xaml

控件模板通過 ListBox 和 ScrollViewer 實現(xiàn)。

<Style TargetType="local:NavScrollPanel">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="local:NavScrollPanel">
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="120" />
                        <ColumnDefinition Width="*" />
                    </Grid.ColumnDefinitions>
                    <ListBox
                        x:Name="PART_ListBox"
                        ItemsSource="{TemplateBinding ItemsSource}"
                        SelectedIndex="{TemplateBinding SelectedIndex}" />
                    <ScrollViewer
                        x:Name="PART_ScrollViewer"
                        Grid.Column="1"
                        VerticalScrollBarVisibility="Auto">
                        <StackPanel x:Name="PART_ContentPanel" />
                    </ScrollViewer>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

3. 使用示例

1. 定義數(shù)據(jù)結構

public class SectionItem {
    public string Title { get; set; }
    public object Content { get; set; }
}

2. 初始化數(shù)據(jù)并綁定

Sections = new ObservableCollection<SectionItem>
{
    new SectionItem{ Title = "播放相關", Content = new PlaybackSettings()},
    new SectionItem{ Title = "桌面歌詞", Content = new DesktopLyrics()},
    new SectionItem{ Title = "快捷鍵", Content = new ShortcutKeys()},
    new SectionItem{ Title = "隱私設置", Content = new PrivacySettings()},
    new SectionItem{ Title = "關于我們", Content = new About()},
};
DataContext = this;

3. 模板定義

<DataTemplate x:Key="SectionTemplate">
    <StackPanel>
        <TextBlock Text="{Binding Title}" FontSize="20" Margin="0,10"/>
        <Border Background="#F0F0F0" Padding="20" CornerRadius="10">
            <ContentPresenter Content="{Binding Content}" FontSize="14"/>
        </Border>
    </StackPanel>
</DataTemplate>

4. 使用控件

<local:NavScrollPanel
    ItemTemplate="{StaticResource SectionTemplate}"
    ItemsSource="{Binding Sections}" />

5. 新增NavScrollPanelExample.xaml

<wd:Window
    x:Class="WpfNavPanel.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="clr-namespace:WpfNavPanel"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:wd="https://github.com/WPFDevelopersOrg/WPFDevelopers"
    Title="NavScrollPanel - 錨點導航"
    Width="800"
    Height="450"
    mc:Ignorable="d">
    <wd:Window.Resources>
        <DataTemplate x:Key="SectionTemplate">
            <StackPanel>
                <TextBlock
                    Margin="0,10"
                    FontSize="20"
                    Text="{Binding Title}" />
                <Border
                    Padding="20"
                    Background="#F0F0F0"
                    CornerRadius="10">
                    <ContentPresenter Content="{Binding Content}" TextElement.FontSize="14" />
                </Border>
            </StackPanel>
        </DataTemplate>
    </wd:Window.Resources>
    <Grid Margin="4">
        <local:NavScrollPanel ItemTemplate="{StaticResource SectionTemplate}" ItemsSource="{Binding Sections}" />
    </Grid>
</wd:Window>

效果如下

到此這篇關于基于WPF實現(xiàn)描點導航功能的文章就介紹到這了,更多相關WPF描點導航內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • C#通過腳本實現(xiàn)接口的示例詳解

    C#通過腳本實現(xiàn)接口的示例詳解

    以前C#腳本用的委托注入模式,今天在提示下,嘗試用腳本直接實現(xiàn)接口,然后C#可以動態(tài)或指定新類型創(chuàng)建接口實現(xiàn)對象,下面我們就來試一下吧
    2025-05-05
  • 基于C#的UDP協(xié)議的同步通信實現(xiàn)代碼

    基于C#的UDP協(xié)議的同步通信實現(xiàn)代碼

    本篇文章主要介紹了基于C#的UDP協(xié)議的同步實現(xiàn)代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-02-02
  • C#數(shù)據(jù)導入到EXCEL的方法

    C#數(shù)據(jù)導入到EXCEL的方法

    今天小編就為大家分享一篇關于C#數(shù)據(jù)導入到EXCEL的方法,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • WinFrom中l(wèi)abel背景透明的實現(xiàn)方法

    WinFrom中l(wèi)abel背景透明的實現(xiàn)方法

    這篇文章主要介紹了WinFrom中l(wèi)abel背景透明的實現(xiàn)方法,方法簡單實用,是C#程序設計中非常實用的技巧,需要的朋友可以參考下
    2014-09-09
  • 關于C# 4.0新特性“缺省參數(shù)”的實現(xiàn)詳解

    關于C# 4.0新特性“缺省參數(shù)”的實現(xiàn)詳解

    這篇文章主要給大家介紹了關于C# 4.0新特性“缺省參數(shù)”的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家學習或者使用C# 4.0具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2020-06-06
  • Audio Source組件及相關API

    Audio Source組件及相關API

    這篇文章主要介紹了Audio Source組件及相關API的相關知識,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2017-11-11
  • 解決Unity urp級聯(lián)陰影接縫問題

    解決Unity urp級聯(lián)陰影接縫問題

    通過從unity內(nèi)部函數(shù)中抽幾個出來改造,強制取某個裁切球的級聯(lián)陰影映射,通過案例給大家詳細介紹,文中給出了完整的urp shader代碼,對Unity級聯(lián)陰影知識感興趣的朋友一起看看吧
    2021-06-06
  • java和c#使用hessian通信的方法

    java和c#使用hessian通信的方法

    這篇文章主要介紹了java和c#使用hessian通信的方法,服務器端為Java,客戶端為C#實現(xiàn)。是一個非常實用的技巧,需要的朋友可以參考下
    2014-09-09
  • WPF實現(xiàn)動態(tài)加載圖片瀏覽器

    WPF實現(xiàn)動態(tài)加載圖片瀏覽器

    這篇文章主要為大家詳細介紹了一種?WPF?+?Prism?實現(xiàn)動態(tài)分頁加載圖片的方法,其中結合了ScrollViewer滾動條觸底檢測,實現(xiàn)邊滾動邊加載的流暢體驗,下面就跟隨小編一起學習一下吧
    2025-04-04
  • C#調(diào)用python.exe使用arcpy方式

    C#調(diào)用python.exe使用arcpy方式

    這篇文章主要介紹了C#調(diào)用python.exe使用arcpy方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12

最新評論

遵义市| 枣强县| 三门峡市| 大埔区| 藁城市| 改则县| 电白县| 山丹县| 东至县| 宝兴县| 余姚市| 虞城县| 尼勒克县| 高雄县| 正阳县| 襄城县| 连山| 洛南县| 连州市| 新田县| 加查县| 新疆| 嫩江县| 吉水县| 西畴县| 杭锦旗| 吴旗县| 酒泉市| 屯门区| 长阳| 长垣县| 浦江县| 枣强县| 驻马店市| 栾川县| 孝义市| 梁河县| 平南县| 西城区| 合江县| 宁蒗|