C# WPF自定义SplitView控件

C# WPF自定义SplitView控件,c#,wpf,xaml,C#,Wpf,Xaml,我只是想说,我看到过类似的帖子,都有同样的问题,但它们给出的解决方案并不适合我的场景。我正在制作一个SplitView控件,如下所示。问题是该控件有3个区域,用户可以在其中放置他们想要的任何控件,但无法通过此错误命名这些控件: 无法在元素“ListViewItem”上设置名称属性值“Item1”ListViewItem“”在元素“SplitView”的作用域下,该元素在另一个作用域中定义时已注册名称 我怎样才能解决这个问题?我不希望这个控件的实现总是需要添加一些代码来绕过这个错误。我是否可以在此

我只是想说,我看到过类似的帖子,都有同样的问题,但它们给出的解决方案并不适合我的场景。我正在制作一个SplitView控件,如下所示。问题是该控件有3个区域,用户可以在其中放置他们想要的任何控件,但无法通过此错误命名这些控件:

无法在元素“ListViewItem”上设置名称属性值“Item1”ListViewItem“”在元素“SplitView”的作用域下,该元素在另一个作用域中定义时已注册名称

我怎样才能解决这个问题?我不希望这个控件的实现总是需要添加一些代码来绕过这个错误。我是否可以在此控件中添加3个模板区域,以便用户可以在每个区域内创建自己的模板,其中包含他们想要的内容。我该怎么做?我对其他想法持开放态度

加价

<UserControl x:Name="ThisControl" x:Class="ns.SplitView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" DataContext="{Binding RelativeSource={RelativeSource Self}}"
             d:DesignHeight="300" d:DesignWidth="300">

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>

        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition/>
        </Grid.RowDefinitions>

        <Button Margin="10" Grid.Row="0" Grid.Column="0" x:Name="OpenPaneButton" Width="50" Height="50" Click="OpenPaneButton_Click" Background="{x:Null}" BorderBrush="{x:Null}" Focusable="False" >
            <Viewbox>
                <Canvas Width="300" Height="210">
                    <Path StrokeThickness="1" StrokeDashArray="" StrokeDashCap="Flat" StrokeDashOffset="0" StrokeStartLineCap="Flat" StrokeEndLineCap="Flat" StrokeLineJoin="Miter" StrokeMiterLimit="10" Stroke="{Binding HamburgerButtonColor, ElementName=ThisControl}" Fill="{Binding HamburgerButtonColor, ElementName=ThisControl}">
                    <Path.Data>
                        <RectangleGeometry Rect="0,0,300,50" RadiusX="25" RadiusY="25" />
                    </Path.Data>
                </Path>
                    <Path StrokeThickness="1" StrokeDashArray="" StrokeDashCap="Flat" StrokeDashOffset="0" StrokeStartLineCap="Flat" StrokeEndLineCap="Flat" StrokeLineJoin="Miter" StrokeMiterLimit="10" Stroke="{Binding HamburgerButtonColor, ElementName=ThisControl}" Fill="{Binding HamburgerButtonColor, ElementName=ThisControl}">
                    <Path.Data>
                        <RectangleGeometry Rect="0,80,300,50" RadiusX="25" RadiusY="25" />
                    </Path.Data>
                </Path>
                    <Path StrokeThickness="1" StrokeDashArray="" StrokeDashCap="Flat" StrokeDashOffset="0" StrokeStartLineCap="Flat" StrokeEndLineCap="Flat" StrokeLineJoin="Miter" StrokeMiterLimit="10" Stroke="{Binding HamburgerButtonColor, ElementName=ThisControl}" Fill="{Binding HamburgerButtonColor, ElementName=ThisControl}">
                    <Path.Data>
                        <RectangleGeometry Rect="0,160,300,50" RadiusX="25" RadiusY="25" />
                    </Path.Data>
                </Path>
            </Canvas>
        </Viewbox>
        </Button>

        <ContentPresenter x:Name="MainTitleContent" Panel.ZIndex="1" Content="{Binding TitleContent, ElementName=ThisControl}" Grid.Row="0" Grid.Column="1" Focusable="True"/>
        <ContentPresenter x:Name="Pane" Panel.ZIndex="1" Grid.ColumnSpan="2" Grid.Column="0" Grid.Row="0" Grid.RowSpan="2" Width="0" HorizontalAlignment="Left" Content="{Binding PaneContent, ElementName=ThisControl}" LostFocus="Pane_LostFocus" LostMouseCapture="Pane_LostMouseCapture" LostKeyboardFocus="Pane_LostKeyboardFocus" LostTouchCapture="Pane_LostTouchCapture" LostStylusCapture="Pane_LostStylusCapture" Focusable="True"/>
        <ContentPresenter x:Name="Content" Grid.ColumnSpan="2" Grid.Column="0" Grid.Row="1" Content="{Binding MainContent, ElementName=ThisControl}" Focusable="True"/>
    </Grid>
</UserControl>

代码隐藏

using System;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;

namespace ns
{
    public partial class SplitView
    {
        /// <summary>
        /// A simple state to know if the pane is open
        /// </summary>
        public bool PaneIsOpen
        {
            get { return (bool)GetValue(PaneIsOpenProperty); }
            set { SetValue(PaneIsOpenProperty, value); }
        }
        public static readonly DependencyProperty PaneIsOpenProperty = DependencyProperty.Register("PaneIsOpen", typeof(bool), typeof(SplitView));

        public SolidColorBrush HamburgerButtonColor
        {
            get { return (SolidColorBrush)GetValue(HamburgerButtonColorProperty); }
            set { SetValue(HamburgerButtonColorProperty, value); }
        }
        public static readonly DependencyProperty HamburgerButtonColorProperty = DependencyProperty.Register("HamburgerButtonColor", typeof(SolidColorBrush), typeof(SplitView), new UIPropertyMetadata(new SolidColorBrush(Colors.Black)));

        public double PaneWidth
        {
            get { return (double)GetValue(PaneWidthProperty); }
            set { SetValue(PaneWidthProperty, value); }
        }
        public static readonly DependencyProperty PaneWidthProperty = DependencyProperty.Register("PaneWidth", typeof(double), typeof(SplitView), new PropertyMetadata(null));
        public object MainContent
        {
            get { return GetValue(MainContentProperty); }
            set { SetValue(MainContentProperty, value); }
        }
        public static readonly DependencyProperty MainContentProperty = DependencyProperty.Register("MainContent", typeof(object), typeof(SplitView), new PropertyMetadata(null));

        public object PaneContent
        {
            get { return GetValue(PaneContentProperty); }
            set { SetValue(PaneContentProperty, value); }
        }
        public static readonly DependencyProperty PaneContentProperty = DependencyProperty.Register("PaneContent", typeof(object), typeof(SplitView), new PropertyMetadata(null));

        public object TitleContent
        {
            get { return GetValue(TitleContentProperty); }
            set { SetValue(TitleContentProperty, value); }
        }
        public static readonly DependencyProperty TitleContentProperty = DependencyProperty.Register("TitleContent", typeof(object), typeof(SplitView), new PropertyMetadata(null));

        private readonly Duration PaneAnimationDuration = new Duration(new TimeSpan());

        private DoubleAnimation ClosePaneAnimation => new DoubleAnimation {Duration = PaneAnimationDuration, To = 0, From = PaneWidth };
        private DoubleAnimation OpenPaneAnimation => new DoubleAnimation {Duration = PaneAnimationDuration, To = PaneWidth, From = 0 };

        public SplitView()
        {
            InitializeComponent();
        }

        private void OpenPaneButton_Click(object sender, RoutedEventArgs e)
        {
            PaneIsOpen = !PaneIsOpen;
            //Debug.WriteLine($"pane is open: {PaneIsOpen}");

            if (PaneIsOpen)
            {
                Pane.BeginAnimation(WidthProperty, OpenPaneAnimation);
                Pane.Focus();
            }

            else
            {
                Pane.BeginAnimation(WidthProperty, ClosePaneAnimation);
            }
        }

        private void Pane_LostFocus(object sender, RoutedEventArgs e)
        {
            PaneLostFocus();
            e.Handled = true;
        }

        private void Pane_LostMouseCapture(object sender, MouseEventArgs e)
        {
            PaneLostFocus();
            e.Handled = true;
        }

        private void PaneLostFocus()
        {
            if (PaneIsOpen)
            {
                PaneIsOpen = false;
                Pane.BeginAnimation(WidthProperty, ClosePaneAnimation);
            }
        }

        private void Pane_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
        {
            PaneLostFocus();
            e.Handled = true;
        }

        private void Pane_LostTouchCapture(object sender, TouchEventArgs e)
        {
            PaneLostFocus();
            e.Handled = true;
        }

        private void Pane_LostStylusCapture(object sender, StylusEventArgs e)
        {
            PaneLostFocus();
            e.Handled = true;
        }
    }
}
使用系统;
使用System.Windows;
使用System.Windows.Input;
使用System.Windows.Media;
使用System.Windows.Media.Animation;
名称空间ns
{
公共部分类拆分视图
{
/// 
///了解窗格是否打开的简单状态
/// 
公共图书馆开放
{
获取{return(bool)GetValue(PaneIsOpenProperty);}
set{SetValue(paneiopenproperty,value);}
}
public static readonly dependencProperty PaneIsOpenProperty=dependencProperty.Register(“PaneIsOpen”、typeof(bool)、typeof(SplitView));
public SolidColorBrush HamburgerButtonColor
{
获取{return(SolidColorBrush)GetValue(HamburgerButtonColorProperty);}
set{SetValue(HamburgerButtonColorProperty,value);}
}
public static readonly dependencProperty HamburgerButtonColorProperty=dependencProperty.Register(“HamburgerButtonColor”、typeof(SolidColorBrush)、typeof(SplitView)、new UIPropertyMetadata(new SolidColorBrush(Colors.Black));
公共双窗格宽度
{
获取{return(double)GetValue(panewithproperty);}
set{SetValue(panewithproperty,value);}
}
public static readonly dependencProperty PaneWidthProperty=dependencProperty.Register(“PaneWidth”、typeof(double)、typeof(SplitView)、newpropertyMetadata(null));
公共对象主要内容
{
获取{返回GetValue(MainContentProperty);}
set{SetValue(MainContentProperty,value);}
}
public static readonly dependencProperty MainContentProperty=dependencProperty.Register(“MainContent”、typeof(object)、typeof(SplitView)、newpropertyMetadata(null));
公共对象泛内容
{
获取{返回GetValue(PaneContentProperty);}
set{SetValue(PaneContentProperty,value);}
}
公共静态只读DependencyProperty PaneContentProperty=DependencyProperty.Register(“PaneContent”、typeof(object)、typeof(SplitView)、new PropertyMetadata(null));
公共对象标题内容
{
获取{返回GetValue(TitleContentProperty);}
set{SetValue(TitleContentProperty,value);}
}
public static readonly dependencProperty TitleContentProperty=dependencProperty.Register(“TitleContent”、typeof(object)、typeof(SplitView)、newpropertyMetadata(null));
私有只读持续时间窗格animationduration=新持续时间(new TimeSpan());
私有DoubleAnimation ClosePaneAnimation=>new DoubleAnimation{Duration=PaneAnimationDuration,To=0,From=PaneWidth};
私有DoubleAnimation OpenPaneAnimation=>new DoubleAnimation{Duration=PaneAnimationDuration,To=PaneWidth,From=0};
公共视图()
{
初始化组件();
}
私有void openpane按钮单击(对象发送器,路由目标)
{
PaneIsOpen=!PaneIsOpen;
//WriteLine($”窗格打开:{PaneIsOpen}”);
如果(窗格打开)
{
窗格.BeginAnimation(WidthProperty,OpenPaneAnimation);
Pane.Focus();
}
其他的
{
窗格.BeginAnimation(WidthProperty,ClosePaneAnimation);
}
}
私有无效窗格\u LostFocus(对象发送方,路由目标)
{
PaneLostFocus();
e、 已处理=正确;
}
私有无效窗格\u LostMouseCapture(对象发送方,鼠标目标e)
{
PaneLostFocus();
e、 已处理=正确;
}
私有void PaneLostFocus()
{
如果(窗格打开)
{
PaneIsOpen=false;
窗格.BeginAnimation(WidthProperty,ClosePaneAnimation);
}
}
私有无效窗格\u LostKeyboardFocus(对象发送器,KeyboardFocusChangedEventArgs e)
{
PaneLostFocus();
e、 已处理=正确;
}
私有无效窗格\u LostTouchCapture(对象发送方,TouchEventArgs e)
{
PaneLostFocus();
e、 已处理=正确;
}
专用空白窗格\u LostStylusCapture(对象发送方,StylusEventArgs e)
{
PaneLostFocus();
e、 已处理=正确;
}
}
}
实施

<customControls:SplitView x:Name="SplitView" PaneWidth="250" HamburgerButtonColor="{StaticResource AccentColorBrush2}">
        <customControls:SplitView.MainContent>
            <Grid>

            </Grid>
        </customControls:SplitView.MainContent>
        <customControls:SplitView.PaneContent>
            <Grid Background="White">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition/>
                </Grid.RowDefinitions>

                <TextBlock Text="Navigation" Style="{StaticResource Header1}"  Margin="10,5,5,5"/>
<!-- I can't name controls in these content areas -->
                <ListView  Grid.Row="1" BorderThickness="0" SelectionChanged="PaneItemsListView_SelectionChanged">
                    <ListViewItem x:Name="Item1" Style="{StaticResource SplitViewItemsStyle}" ">
                        <TextBlock Text="Project Explorer" Margin="20,5,10,5"/>
                    </ListViewItem>
                    <ListViewItem Style="{StaticResource SplitViewItemsStyle}" Tag="FieldServicesItem">
                        <TextBlock Text="Field Services" Margin="20,5,10,5"/>
                    </ListViewItem>
                    <ListViewItem Style="{StaticResource SplitViewItemsStyle}" Tag="ReportManagerItem">
                        <TextBlock Text="Report Manager" Margin="20,5,10,5"/>
                    </ListViewItem>
                </ListView>
            </Grid>
        </customControls:SplitView.PaneContent>
        <customControls:SplitView.TitleContent>
            <Grid>
                <TextBlock HorizontalAlignment="Center" Text="Current View" VerticalAlignment="Center" Style="{StaticResource Header1}"/>
            </Grid>
        </customControls:SplitView.TitleContent>
    </customControls:SplitView>