【问题标题】:Dynamically Create Draggable UserControl in Win8 Metro App在 Win8 Metro App 中动态创建可拖动的 UserControl
【发布时间】:2013-12-09 16:57:32
【问题描述】:

此刻我有一个视图,它使用绑定到用户列表的磁贴填充 ListView。 OnClick 任何这些 Tiles(buttons) 我需要动态创建一个小的可拖动窗口,该窗口由包含 ScrollViewer&ItemsControl、Textbox 和 Button 的 StackPanel 组成。然后必须根据单击的用户 Tile 将其绑定到 ObservableCollection。

这将用于私人聊天场景。

我已经实现了一个绑定到 ObservableCollection 的群聊,但这是在导航到页面时创建的。

我已经开始将相同的控件集添加到 Resources.xaml 的 dataTemplate 中,但我不知道下一步该去哪里。

<DataTemplate x:Key="PrivateChatTemplate">
    <StackPanel Width="267" Height="300" >
        <ScrollViewer x:Name="PrivateScrollViewer" Grid.ColumnSpan="2" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto" >
            <ItemsControl Name="PrivateItemsControl" Foreground="Black" />
        </ScrollViewer>
        <TextBox x:Name="PrivateTextBox" HorizontalAlignment="Left" TextWrapping="Wrap" VerticalAlignment="Top" Width="201" Height="60" BorderThickness="1" BorderBrush="Black"/>
        <Button x:Name="PrivateSendButton" Content="Send" HorizontalAlignment="Left" Height="58" Margin="65,2,0,0" VerticalAlignment="Top" Width="66"   Click="PrivateSendButton_Click" Background="Black"/>
    </StackPanel>       
</DataTemplate>

感谢您的帮助。

【问题讨论】:

    标签: c# xaml windows-runtime microsoft-metro datatemplate


    【解决方案1】:

    有趣的是,您提到了 ScrollViewer,因为这让我想到了使用 ScrollViewer 在其他内容前面放置一个类似前景窗口的控件,而且相当简单。

    在您的页面内 - 放置一个延伸到整个应用窗口大小的ScrollViewer(通过将VerticalAlignmentHorizontalAlignment 都设置为Stretch),它有一个Panel,就像CanvasGrid 在其中并将 window/UserControl 放在其中 - 就像下面代码中的 Rectangle 一样。通过将-ScrollMode/-ScrollBarVisibility 值和面板大小设置为大于ScrollViewer's ViewportWidthViewportHeight,确保ScrollViewer 可以双向滚动。您应该在ScrollViewer 和其中的窗口上处理SizeChanged 事件,并将面板的WidthHeight 设置为类似

    panel.Width = scrollViewer.ViewportWidth * 2 - window.ActualWidth;
    panel.Height = scrollViewer.ViewportHeight * 2 - window.ActualWidth;
    

    现在一切都应该可以通过触摸滚动了。剩下的问题是根据窗口上的Pointer- 事件处理鼠标输入。

    XAML

    <Page
        x:Class="DraggableWindow.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:DraggableWindow"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
    
        <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
            <Button
                Content="Button"
                HorizontalAlignment="Left"
                Height="99"
                Margin="112,101,0,0"
                VerticalAlignment="Top"
                Width="119" />
            <Button
                Content="Button"
                HorizontalAlignment="Left"
                Height="147"
                Margin="985,389,0,0"
                VerticalAlignment="Top"
                Width="262" />
            <Button
                Content="Button"
                HorizontalAlignment="Left"
                Height="147"
                Margin="403,581,0,0"
                VerticalAlignment="Top"
                Width="262" />
            <Button
                Content="Button"
                HorizontalAlignment="Left"
                Height="147"
                Margin="112,277,0,0"
                VerticalAlignment="Top"
                Width="262" />
            <Button
                Content="Button"
                HorizontalAlignment="Left"
                Height="147"
                Margin="682,129,0,0"
                VerticalAlignment="Top"
                Width="262" />
            <Button
                Content="Button"
                HorizontalAlignment="Left"
                Height="147"
                Margin="551,371,0,0"
                VerticalAlignment="Top"
                Width="262" />
            <ScrollViewer
                x:Name="scrollViewer"
                SizeChanged="OnScrollViewerSizeChanged"
                Background="{x:Null}"
                HorizontalAlignment="Stretch"
                VerticalAlignment="Stretch"
                HorizontalScrollMode="Auto"
                HorizontalScrollBarVisibility="Hidden"
                VerticalScrollBarVisibility="Hidden"
                IsHorizontalRailEnabled="False"
                IsVerticalRailEnabled="False">
                <Canvas
                    x:Name="panel">
                    <Rectangle
                        x:Name="window"
                        SizeChanged="OnWindowSizeChanged"
                        PointerPressed="OnWindowPointerPressed"
                        PointerMoved="OnWindowPointerMoved"
                        PointerReleased="OnWindowPointerReleased"
                        Fill="LightGray"
                        Width="200"
                        Height="150"/>
                </Canvas>
            </ScrollViewer>
        </Grid>
    </Page>
    

    C# 使用 Windows.Devices.Input; 使用 Windows.Foundation; 使用 Windows.UI.Xaml; 使用 Windows.UI.Xaml.Controls; 使用 Windows.UI.Xaml.Input;

    namespace DraggableWindow
    {
        public sealed partial class MainPage : Page
        {
            public MainPage()
            {
                this.InitializeComponent();
            }
    
            private uint pointerId;
            private Point lastPoint;
    
            private void OnWindowPointerPressed(object sender, PointerRoutedEventArgs e)
            {
                if (e.Pointer.PointerDeviceType == PointerDeviceType.Mouse)
                {
                    window.CapturePointer(e.Pointer);
                    this.pointerId = e.Pointer.PointerId;
                    this.lastPoint = e.GetCurrentPoint(window).Position;
                }
            }
    
            private void OnWindowPointerMoved(object sender, PointerRoutedEventArgs e)
            {
                if (e.Pointer.IsInContact &&
                    e.Pointer.PointerId == pointerId)
                {
                    var point = e.GetCurrentPoint(window).Position;
                    this.scrollViewer.ChangeView(
                        this.scrollViewer.HorizontalOffset - point.X + lastPoint.X,
                        this.scrollViewer.VerticalOffset - point.Y + lastPoint.Y,
                        null,
                        true);
                }
            }
    
            private void OnWindowPointerReleased(object sender, PointerRoutedEventArgs e)
            {
                if (e.Pointer.PointerId == pointerId)
                {
                    window.ReleasePointerCapture(e.Pointer);
                }
            }
    
            private void OnScrollViewerSizeChanged(object sender, SizeChangedEventArgs e)
            {
                UpdateWindowingLayout();
            }
    
            private void OnWindowSizeChanged(object sender, SizeChangedEventArgs e)
            {
                UpdateWindowingLayout();
            }
    
            private void UpdateWindowingLayout()
            {
                this.panel.Width = this.scrollViewer.ViewportWidth * 2 - 0.0 * this.window.ActualWidth;
                this.panel.Height = this.scrollViewer.ViewportHeight * 2 - 0.5 * this.window.ActualHeight;
                Canvas.SetLeft(this.window, this.scrollViewer.ViewportWidth - 0.5 * this.window.ActualWidth);
                Canvas.SetTop(this.window, this.scrollViewer.ViewportHeight - 0.5 * this.window.ActualHeight);
            }
        }
    }
    

    哦,让这一切变得动态 - 将其包装在 UserControl 中以处理那里的事件并将其放入 Popup 中。当我有机会时,我会看到将所有这些都包装在一个可重用的控件中,因为我的可视化树调试器叠加层也需要类似的东西。

    【讨论】:

    • 正如我现在所看到的 - ScrollViewer 在这里似乎没有多大帮助,因为无论如何您都需要自己处理输入。一个更好的解决方案可能是 Diederik 在他的article 中描述的。不过,我刚刚开始使用自己的窗口控件。
    【解决方案2】:

    @Filip Skakun 不幸的是,我必须使用 8.0 而不是 8.1,所以没有新的 ChangeView 方法。我试图制作一个自定义 UserControl,但我不确定如何处理 SizeChanged 和 UpdateWindowingLayout,因为窗口将在单击按钮时创建,本质上是动态创建的。然后,我需要将字符串列表绑定到 UserControl 内的 ItemsControl。
    `不幸的是,我必须使用 8.0 而不是 8.1,所以没有新的 ChangeView 方法。我试图制作一个自定义的 UserControl,但我不确定如何处理 SizeChanged 和 UpdateWindowingLayout(以实现拖动),因为窗口将在单击按钮时创建,本质上是动态创建的。然后我需要将字符串列表绑定到 UserControl 内的 ItemsControl。 '

        <UserControl
    x:Class="KeyOui.View.PrivateChatWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:KeyOui.View"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="200"
    d:DesignWidth="300">
    
    <StackPanel Background="Indigo">
        <ScrollViewer>
            <ItemsControl Name="PrivateChatItemsControl" ItemsSource="{Binding ListOfMessages.Name}" Width="Auto" Height="150" Foreground="Black" BorderBrush="Gray" BorderThickness="2" />
        </ScrollViewer>
        <StackPanel VerticalAlignment="Stretch" Orientation="Horizontal" HorizontalAlignment="Stretch">
            <TextBox x:Name="GroupChatTextBox" VerticalAlignment="Bottom" TextWrapping="Wrap" FontSize="14" Width="140" Height="40" Margin="5,5,5,5" BorderThickness="1" BorderBrush="Gray"/>
            <Button x:Name="SendButton" Content="Send"  
                            HorizontalAlignment="Left" Height="40" 
                            VerticalAlignment="Top" Width="Auto"  
                            Click="SendButton_Click"  Margin="5,5,5,5"
                            BorderThickness="1" BorderBrush="Gray"/>
        </StackPanel>
    </StackPanel>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-16
      • 1970-01-01
      • 1970-01-01
      • 2015-04-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多