精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

WPF多窗口開發(fā)實(shí)戰(zhàn):從入門到精通的完整指南

開發(fā) 前端
今天,我將通過一個(gè)完整的實(shí)戰(zhàn)項(xiàng)目,帶你從零開始掌握WPF多窗口開發(fā)的所有核心技術(shù)。這不僅僅是理論講解,而是一套可以直接應(yīng)用到項(xiàng)目中的完整解決方案!

你是否還在為WPF應(yīng)用中的窗口跳轉(zhuǎn)而頭疼?多個(gè)窗口之間如何優(yōu)雅地傳遞數(shù)據(jù)?模態(tài)和非模態(tài)窗口有什么區(qū)別?其實(shí)這里與Winform基本一回事,這里講的不是導(dǎo)航。作為一名C#開發(fā)者,掌握多窗口開發(fā)技巧是構(gòu)建專業(yè)級桌面應(yīng)用的必備技能。

今天,我將通過一個(gè)完整的實(shí)戰(zhàn)項(xiàng)目,帶你從零開始掌握WPF多窗口開發(fā)的所有核心技術(shù)。這不僅僅是理論講解,而是一套可以直接應(yīng)用到項(xiàng)目中的完整解決方案!

為什么需要多窗口開發(fā)?

現(xiàn)實(shí)開發(fā)痛點(diǎn)

在實(shí)際項(xiàng)目中,我們經(jīng)常遇到這些場景:

  • 設(shè)置窗口需要獨(dú)立的配置界面
  • 數(shù)據(jù)錄入復(fù)雜表單需要分步驟完成
  • 信息展示詳情頁面需要獨(dú)立顯示
  • 工具窗口調(diào)試或輔助功能窗口

單窗口應(yīng)用雖然簡單,但用戶體驗(yàn)往往不夠友好,多窗口設(shè)計(jì)能帶來更好的交互體驗(yàn)和功能分離。

核心技術(shù)解析

模態(tài) vs 非模態(tài)窗口

模態(tài)窗口(Modal)特點(diǎn):

  • 阻塞父窗口操作
  • 必須處理完當(dāng)前窗口才能繼續(xù)
  • 適用于:確認(rèn)對話框、設(shè)置頁面、數(shù)據(jù)錄入

非模態(tài)窗口(Modeless)特點(diǎn):

  • 不阻塞父窗口
  • 可以同時(shí)操作多個(gè)窗口
  • 適用于:工具欄、實(shí)時(shí)監(jiān)控、輔助功能
// 模態(tài)窗口顯示
SecondWindow modal = new SecondWindow();
bool? result = modal.ShowDialog(); // 阻塞執(zhí)行

// 非模態(tài)窗口顯示
ThirdWindow modeless = new ThirdWindow();
modeless.Show(); // 立即返回,不阻塞

窗口間通信的三種方式

1?? 構(gòu)造函數(shù)傳參(單向傳遞)

public SecondWindow(string userName)
{
    InitializeComponent();
    this.userName = userName;
    txtWelcome.Text = $"歡迎,{userName}!";
}

2?? 屬性返回值(模態(tài)窗口返回?cái)?shù)據(jù))

public class SecondWindow : Window
{
    publicstring ReturnData { get; privateset; } = "無數(shù)據(jù)";

    private void btnConfirm_Click(object sender, RoutedEventArgs e)
    {
        ReturnData = "用戶提交的數(shù)據(jù)";
        this.DialogResult = true; // 關(guān)鍵:設(shè)置返回值
    }
}

// 主窗口接收
bool? result = secondWindow.ShowDialog();
if (result == true)
{
    string data = secondWindow.ReturnData;
}

3?? 事件機(jī)制(實(shí)時(shí)通信)

public class ThirdWindow : Window
{
    public event EventHandler<string> DataReceived;

    private void SendMessage()
    {
        DataReceived?.Invoke(this, "來自子窗口的消息");
    }
}

// 主窗口訂閱事件
thirdWindow.DataReceived += (sender, data) => {
    AddMessage($"接收到數(shù)據(jù):{data}");
};

完整實(shí)戰(zhàn)代碼

主窗口核心代碼

public partial class MainWindow : Window
{
    private List<Window> openWindows = new List<Window>();

    // 打開模態(tài)窗口
    private void btnOpenSecond_Click(object sender, RoutedEventArgs e)
    {
        string userName = txtUserName.Text.Trim();
        if (string.IsNullOrEmpty(userName))
        {
            MessageBox.Show("請先輸入您的姓名!", "提示");
            return;
        }

        SecondWindow secondWindow = new SecondWindow(userName);
        secondWindow.Owner = this; // ? 關(guān)鍵:設(shè)置父窗口

        bool? result = secondWindow.ShowDialog();
        if (result == true)
        {
            AddMessage($"接收到數(shù)據(jù):{secondWindow.ReturnData}");
        }
    }

    // 打開非模態(tài)窗口
    private void btnOpenThird_Click(object sender, RoutedEventArgs e)
    {
        ThirdWindow thirdWindow = new ThirdWindow(txtUserName.Text);
        thirdWindow.Owner = this;
        thirdWindow.DataReceived += (sender, data) => {
            AddMessage($"實(shí)時(shí)消息:{data}");
        };

        openWindows.Add(thirdWindow);
        thirdWindow.Show(); // 非阻塞顯示
    }
}

子窗口設(shè)計(jì)要點(diǎn)

模態(tài)窗口(數(shù)據(jù)收集)

public partial class SecondWindow : Window
{
    publicstring ReturnData { get; privateset; }

    private void btnConfirm_Click(object sender, RoutedEventArgs e)
    {
        // ? 數(shù)據(jù)驗(yàn)證
        if (cmbProfession.SelectedItem == null)
        {
            MessageBox.Show("請選擇職業(yè)!");
            return;
        }

        // ? 收集并格式化數(shù)據(jù)
        ReturnData = BuildUserData();
        this.DialogResult = true; // 設(shè)置返回結(jié)果
    }

    private string BuildUserData()
    {
        var profession = ((ComboBoxItem)cmbProfession.SelectedItem).Content;
        var experience = (int)sliderExperience.Value;
        return $"職業(yè): {profession}, 經(jīng)驗(yàn): {experience}年";
    }
}

非模態(tài)窗口(實(shí)時(shí)交互)

public partial class ThirdWindow : Window
{
    public event EventHandler<string> DataReceived;
    private DispatcherTimer timer;

    public ThirdWindow(string userName)
    {
        InitializeComponent();
        InitializeTimer(); // ? 初始化定時(shí)器
    }

    private void InitializeTimer()
    {
        timer = new DispatcherTimer
        {
            Interval = TimeSpan.FromSeconds(1)
        };
        timer.Tick += (s, e) => {
            txtCurrentTime.Text = DateTime.Now.ToString("HH:mm:ss");
        };
        timer.Start();
    }

    private void btnSendMessage_Click(object sender, RoutedEventArgs e)
    {
        string message = txtMessage.Text.Trim();
        if (!string.IsNullOrEmpty(message))
        {
            DataReceived?.Invoke(this, message); // ? 觸發(fā)事件
            txtMessage.Clear();
        }
    }
}

完整代碼

MainWindow

<Window x:Class="AppWpfWindows.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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:AppWpfWindows"
        mc:Ignorable="d"
        Title="MainWindow" Height="620
        " Width="800">
    <Grid Margin="20">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <TextBlock Grid.Row="0" Text="多窗口應(yīng)用程序演示"
                   FontSize="24" FontWeight="Bold"
                   HorizontalAlignment="Center"
                   Foreground="#2E8B57" Margin="0,0,0,20"/>

        <StackPanel Grid.Row="1" Orientation="Horizontal" Margin="0,10">
            <TextBlock Text="輸入您的姓名:" VerticalAlignment="Center"
                       FontSize="14" Width="100"/>
            <TextBox x:Name="txtUserName" Width="200" Height="30"
                     FontSize="14" Padding="5"/>
        </StackPanel>

        <GroupBox Grid.Row="2" Header="窗口操作" Margin="0,20,0,10"
                  FontWeight="Bold" Foreground="#2E8B57">
            <StackPanel Margin="10">
                <Button x:Name="btnOpenSecond" Content="打開第二個(gè)窗口 (模態(tài))"
                        Height="35" Margin="5" FontSize="14"
                        Background="#87CEEB" BorderBrush="#4682B4"
                        Click="btnOpenSecond_Click"/>

                <Button x:Name="btnOpenThird" Content="打開第三個(gè)窗口 (非模態(tài))"
                        Height="35" Margin="5" FontSize="14"
                        Background="#98FB98" BorderBrush="#32CD32"
                        Click="btnOpenThird_Click"/>

                <Button x:Name="btnShowAllWindows" Content="顯示所有打開的窗口"
                        Height="35" Margin="5" FontSize="14"
                        Background="#F0E68C" BorderBrush="#DAA520"
                        Click="btnShowAllWindows_Click"/>
            </StackPanel>
        </GroupBox>

        <GroupBox Grid.Row="3" Header="消息日志" Margin="0,10"
                  FontWeight="Bold" Foreground="#2E8B57">
            <ScrollViewer Height="100" Margin="5">
                <TextBlock x:Name="txtMessages" FontSize="12"
                           TextWrapping="Wrap" Foreground="#333"/>
            </ScrollViewer>
        </GroupBox>


        <TextBlock Grid.Row="4" x:Name="txtWindowInfo"
                   FontSize="12" Foreground="#666"
                   VerticalAlignment="Bottom" Margin="0,10"/>

        <Button Grid.Row="5" x:Name="btnExit" Content="退出應(yīng)用程序"
                Height="30" Width="120"
                Background="#FFB6C1" BorderBrush="#DC143C"
                HorizontalAlignment="Right"
                Click="btnExit_Click"/>
    </Grid>
</Window>
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace AppWpfWindows
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private List<Window> openWindows = new List<Window>();

        public MainWindow()
        {
            InitializeComponent();
            this.Loaded += MainWindow_Loaded;
            this.Closing += MainWindow_Closing;
        }

        private void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            AddMessage("主窗口已加載");
            UpdateWindowInfo();
        }

        private void MainWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            // 關(guān)閉所有子窗口
            foreach (var window in openWindows.ToList())
            {
                if (window.IsLoaded)
                {
                    window.Close();
                }
            }
        }

        private void btnOpenSecond_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                string userName = txtUserName.Text.Trim();
                if (string.IsNullOrEmpty(userName))
                {
                    MessageBox.Show("請先輸入您的姓名!", "提示",
                                  MessageBoxButton.OK, MessageBoxImage.Warning);
                    return;
                }

                SecondWindow secondWindow = new SecondWindow(userName);
                secondWindow.Owner = this; // 設(shè)置父窗口
                secondWindow.WindowClosed += SecondWindow_WindowClosed;

                openWindows.Add(secondWindow);
                AddMessage($"正在以模態(tài)方式打開第二個(gè)窗口,用戶:{userName}");

                // 模態(tài)顯示
                bool? result = secondWindow.ShowDialog();

                if (result == true)
                {
                    AddMessage("第二個(gè)窗口返回了確定結(jié)果");
                }
                else
                {
                    AddMessage("第二個(gè)窗口被取消或關(guān)閉");
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"打開窗口時(shí)發(fā)生錯(cuò)誤:{ex.Message}", "錯(cuò)誤",
                              MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        private void btnOpenThird_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                string userName = txtUserName.Text.Trim();
                if (string.IsNullOrEmpty(userName))
                {
                    userName = "匿名用戶";
                }

                ThirdWindow thirdWindow = new ThirdWindow(userName);
                thirdWindow.Owner = this; // 設(shè)置父窗口
                thirdWindow.WindowClosed += ThirdWindow_WindowClosed;
                thirdWindow.DataReceived += ThirdWindow_DataReceived;

                openWindows.Add(thirdWindow);
                AddMessage($"正在以非模態(tài)方式打開第三個(gè)窗口,用戶:{userName}");

                // 非模態(tài)顯示
                thirdWindow.Show();

                UpdateWindowInfo();
            }
            catch (Exception ex)
            {
                MessageBox.Show($"打開窗口時(shí)發(fā)生錯(cuò)誤:{ex.Message}", "錯(cuò)誤",
                              MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        private void btnShowAllWindows_Click(object sender, RoutedEventArgs e)
        {
            var openWindowsList = openWindows.Where(w => w.IsLoaded).ToList();

            if (openWindowsList.Count == 0)
            {
                AddMessage("當(dāng)前沒有打開的子窗口");
                return;
            }

            string windowsList = string.Join("\n",
                openWindowsList.Select(w => $"- {w.Title} ({w.GetType().Name})"));

            MessageBox.Show($"當(dāng)前打開的窗口:\n{windowsList}",
                          "窗口列表", MessageBoxButton.OK, MessageBoxImage.Information);

            AddMessage($"顯示了 {openWindowsList.Count} 個(gè)打開的窗口信息");
        }

        private void btnExit_Click(object sender, RoutedEventArgs e)
        {
            if (MessageBox.Show("確定要退出應(yīng)用程序嗎?", "確認(rèn)退出",
                              MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
            {
                Application.Current.Shutdown();
            }
        }

        private void SecondWindow_WindowClosed(object sender, EventArgs e)
        {
            if (sender is SecondWindow window)
            {
                openWindows.Remove(window);
                AddMessage($"第二個(gè)窗口已關(guān)閉,返回?cái)?shù)據(jù):{window.ReturnData}");
                UpdateWindowInfo();
            }
        }

        private void ThirdWindow_WindowClosed(object sender, EventArgs e)
        {
            if (sender is ThirdWindow window)
            {
                openWindows.Remove(window);
                AddMessage("第三個(gè)窗口已關(guān)閉");
                UpdateWindowInfo();
            }
        }

        private void ThirdWindow_DataReceived(object sender, string data)
        {
            AddMessage($"從第三個(gè)窗口接收到數(shù)據(jù):{data}");
        }

        private void AddMessage(string message)
        {
            string timeStamp = DateTime.Now.ToString("HH:mm:ss");
            txtMessages.Text += $"[{timeStamp}] {message}\n";

            // 自動(dòng)滾動(dòng)到底部
            if (txtMessages.Parent is ScrollViewer scrollViewer)
            {
                scrollViewer.ScrollToBottom();
            }
        }

        private void UpdateWindowInfo()
        {
            var openCount = openWindows.Count(w => w.IsLoaded);
            txtWindowInfo.Text = $"窗口信息:主窗口 | 打開的子窗口數(shù)量:{openCount}";
        }
    }
}

SecondWindow

<Window x:Class="AppWpfWindows.SecondWindow"
        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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:AppWpfWindows"
        mc:Ignorable="d"
        Title="SecondWindow" Height="500" Width="800">
    <Grid Margin="20">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <TextBlock Grid.Row="0" x:Name="txtWelcome"
                   FontSize="18" FontWeight="Bold"
                   HorizontalAlignment="Center"
                   Foreground="#8B4513" Margin="0,0,0,15"/>

        <GroupBox Grid.Row="1" Header="數(shù)據(jù)輸入" Margin="0,10"
                  FontWeight="Bold" Foreground="#8B4513">
            <StackPanel Margin="10">
                <StackPanel Orientation="Horizontal" Margin="0,5">
                    <TextBlock Text="選擇您的職業(yè):" Width="100" VerticalAlignment="Center"/>
                    <ComboBox x:Name="cmbProfession" Width="200" Height="25">
                        <ComboBoxItem Content="軟件工程師"/>
                        <ComboBoxItem Content="產(chǎn)品經(jīng)理"/>
                        <ComboBoxItem Content="UI設(shè)計(jì)師"/>
                        <ComboBoxItem Content="測試工程師"/>
                        <ComboBoxItem Content="其他"/>
                    </ComboBox>
                </StackPanel>

                <StackPanel Orientation="Horizontal" Margin="0,5">
                    <TextBlock Text="工作經(jīng)驗(yàn):" Width="100" VerticalAlignment="Center"/>
                    <Slider x:Name="sliderExperience" Width="150" Minimum="0" Maximum="20"
                            Value="1" TickFrequency="1" IsSnapToTickEnabled="True"/>
                    <TextBlock x:Name="txtExperienceValue" Text="1 年"
                               VerticalAlignment="Center" Margin="10,0"/>
                </StackPanel>
            </StackPanel>
        </GroupBox>

        <GroupBox Grid.Row="2" Header="個(gè)人偏好" Margin="0,10"
                  FontWeight="Bold" Foreground="#8B4513">
            <StackPanel Margin="10">
                <CheckBox x:Name="chkNewsletter" Content="訂閱技術(shù)通訊" Margin="0,3"/>
                <CheckBox x:Name="chkUpdates" Content="接收產(chǎn)品更新" Margin="0,3"/>
                <CheckBox x:Name="chkPromotions" Content="接收優(yōu)惠信息" Margin="0,3"/>
            </StackPanel>
        </GroupBox>

        <GroupBox Grid.Row="3" Header="備注" Margin="0,10"
                  FontWeight="Bold" Foreground="#8B4513">
            <TextBox x:Name="txtComments" TextWrapping="Wrap"
                     AcceptsReturn="True" Margin="5"
                     VerticalScrollBarVisibility="Auto"/>
        </GroupBox>

        <StackPanel Grid.Row="4" Orientation="Horizontal"
                    HorizontalAlignment="Right" Margin="0,15,0,0">
            <Button x:Name="btnConfirm" Content="確認(rèn)" Width="80" Height="30"
                    Margin="5" Background="#90EE90" BorderBrush="#32CD32"
                    Click="btnConfirm_Click"/>
            <Button x:Name="btnCancel" Content="取消" Width="80" Height="30"
                    Margin="5" Background="#FFB6C1" BorderBrush="#DC143C"
                    Click="btnCancel_Click"/>
        </StackPanel>
    </Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace AppWpfWindows
{
    /// <summary>
    /// Interaction logic for SecondWindow.xaml
    /// </summary>
    public partial class SecondWindow : Window
    {
        public event EventHandler WindowClosed;
        publicstring ReturnData { get; privateset; } = "無數(shù)據(jù)";
        privatestring userName;

        public SecondWindow(string userName)
        {
            InitializeComponent();
            this.userName = userName;
            this.Loaded += SecondWindow_Loaded;
            this.Closing += SecondWindow_Closing;

            // 綁定滑塊值變化事件
            sliderExperience.ValueChanged += SliderExperience_ValueChanged;
        }

        private void SecondWindow_Loaded(object sender, RoutedEventArgs e)
        {
            txtWelcome.Text = $"歡迎,{userName}!";

            // 設(shè)置默認(rèn)值
            cmbProfession.SelectedIndex = 0;
            UpdateExperienceDisplay();
        }

        private void SecondWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            WindowClosed?.Invoke(this, EventArgs.Empty);
        }

        private void SliderExperience_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            UpdateExperienceDisplay();
        }

        private void UpdateExperienceDisplay()
        {
            if (txtExperienceValue != null)
            {
                int years = (int)sliderExperience.Value;
                txtExperienceValue.Text = $"{years} 年";
            }
        }

        private void btnConfirm_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                // 驗(yàn)證必要輸入
                if (cmbProfession.SelectedItem == null)
                {
                    MessageBox.Show("請選擇您的職業(yè)!", "提示",
                                  MessageBoxButton.OK, MessageBoxImage.Warning);
                    return;
                }

                // 收集數(shù)據(jù)
                var selectedProfession = ((ComboBoxItem)cmbProfession.SelectedItem).Content.ToString();
                var experience = (int)sliderExperience.Value;
                var preferences = new List<string>();

                if (chkNewsletter.IsChecked == true) preferences.Add("技術(shù)通訊");
                if (chkUpdates.IsChecked == true) preferences.Add("產(chǎn)品更新");
                if (chkPromotions.IsChecked == true) preferences.Add("優(yōu)惠信息");

                var comments = txtComments.Text.Trim();

                // 構(gòu)建返回?cái)?shù)據(jù)
                ReturnData = $"職業(yè): {selectedProfession}, " +
                           $"經(jīng)驗(yàn): {experience}年, " +
                           $"偏好: {string.Join(",", preferences)}" +
                           (string.IsNullOrEmpty(comments) ? "" : $", 備注: {comments}");

                // 顯示確認(rèn)信息
                var result = MessageBox.Show(
                    $"確認(rèn)提交以下信息?\n\n{ReturnData}",
                    "確認(rèn)信息",
                    MessageBoxButton.YesNo,
                    MessageBoxImage.Question);

                if (result == MessageBoxResult.Yes)
                {
                    this.DialogResult = true;
                    this.Close();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"處理數(shù)據(jù)時(shí)發(fā)生錯(cuò)誤:{ex.Message}", "錯(cuò)誤",
                              MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        private void btnCancel_Click(object sender, RoutedEventArgs e)
        {
            ReturnData = "用戶取消操作";
            this.DialogResult = false;
            this.Close();
        }
    }
}

ThirdWindow

<Window x:Class="AppWpfWindows.ThirdWindow"
        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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:AppWpfWindows"
        mc:Ignorable="d"
        Title="ThirdWindow" Height="500" Width="800">
    <Grid Margin="15">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <TextBlock Grid.Row="0" x:Name="txtTitle"
                   FontSize="20" FontWeight="Bold"
                   HorizontalAlignment="Center"
                   Foreground="#4B0082" Margin="0,0,0,15"/>

        <GroupBox Grid.Row="1" Header="實(shí)時(shí)信息" Margin="0,5"
                  FontWeight="Bold" Foreground="#4B0082">
            <StackPanel Margin="10">
                <StackPanel Orientation="Horizontal" Margin="0,5">
                    <TextBlock Text="當(dāng)前時(shí)間:" Width="80" VerticalAlignment="Center"/>
                    <TextBlock x:Name="txtCurrentTime" FontSize="14"
                               FontWeight="Bold" Foreground="#8B008B"/>
                </StackPanel>

                <StackPanel Orientation="Horizontal" Margin="0,5">
                    <TextBlock Text="窗口狀態(tài):" Width="80" VerticalAlignment="Center"/>
                    <TextBlock x:Name="txtWindowStatus" FontSize="12"
                               Foreground="#8B008B"/>
                </StackPanel>
            </StackPanel>
        </GroupBox>

        <GroupBox Grid.Row="2" Header="消息中心" Margin="0,10"
                  FontWeight="Bold" Foreground="#4B0082">
            <Grid Margin="10">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="*"/>
                    <RowDefinition Height="Auto"/>
                </Grid.RowDefinitions>

                <TextBlock Grid.Row="0" Text="發(fā)送消息到主窗口:" Margin="0,0,0,5"/>

                <TextBox Grid.Row="1" x:Name="txtMessage"
                         TextWrapping="Wrap" AcceptsReturn="True"
                         VerticalScrollBarVisibility="Auto"
                         FontSize="12" Margin="0,0,0,10"/>

                <StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Right">
                    <Button x:Name="btnSendMessage" Content="發(fā)送消息"
                            Width="80" Height="25" Margin="5,0"
                            Background="#DDA0DD" BorderBrush="#9370DB"
                            Click="btnSendMessage_Click"/>
                    <Button x:Name="btnClearMessage" Content="清除"
                            Width="60" Height="25" Margin="5,0"
                            Background="#F0E68C" BorderBrush="#DAA520"
                            Click="btnClearMessage_Click"/>
                </StackPanel>
            </Grid>
        </GroupBox>

        <GroupBox Grid.Row="3" Header="窗口操作" Margin="0,10"
                  FontWeight="Bold" Foreground="#4B0082">
            <StackPanel Orientation="Horizontal" Margin="10" HorizontalAlignment="Center">
                <Button x:Name="btnMinimize" Content="最小化"
                        Width="70" Height="25" Margin="5"
                        Background="#87CEEB" BorderBrush="#4682B4"
                        Click="btnMinimize_Click"/>
                <Button x:Name="btnToggleTopmost" Content="置頂切換"
                        Width="70" Height="25" Margin="5"
                        Background="#98FB98" BorderBrush="#32CD32"
                        Click="btnToggleTopmost_Click"/>
                <Button x:Name="btnChangePosition" Content="改變位置"
                        Width="70" Height="25" Margin="5"
                        Background="#F0E68C" BorderBrush="#DAA520"
                        Click="btnChangePosition_Click"/>
            </StackPanel>
        </GroupBox>

        <Button Grid.Row="4" x:Name="btnClose" Content="關(guān)閉窗口"
                Width="100" Height="30" Margin="0,15,0,0"
                Background="#FFB6C1" BorderBrush="#DC143C"
                HorizontalAlignment="Right"
                Click="btnClose_Click"/>
    </Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Windows.Threading;

namespace AppWpfWindows
{
    /// <summary>
    /// Interaction logic for ThirdWindow.xaml
    /// </summary>
    public partial class ThirdWindow : Window
    {
        public event EventHandler WindowClosed;
        public event EventHandler<string> DataReceived;

        private DispatcherTimer timer;
        privatestring userName;
        private Random random = new Random();

        public ThirdWindow(string userName)
        {
            InitializeComponent();
            this.userName = userName;
            this.Loaded += ThirdWindow_Loaded;
            this.Closing += ThirdWindow_Closing;
            this.StateChanged += ThirdWindow_StateChanged;

            InitializeTimer();
        }

        private void ThirdWindow_Loaded(object sender, RoutedEventArgs e)
        {
            txtTitle.Text = $"{userName} 的工作空間";
            UpdateWindowStatus();

            // 設(shè)置窗口初始位置(相對于父窗口偏移)
            if (this.Owner != null)
            {
                this.Left = this.Owner.Left + 50;
                this.Top = this.Owner.Top + 50;
            }

            timer.Start();
        }

        private void ThirdWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            timer?.Stop();
            WindowClosed?.Invoke(this, EventArgs.Empty);
        }

        private void ThirdWindow_StateChanged(object sender, EventArgs e)
        {
            UpdateWindowStatus();
        }

        private void InitializeTimer()
        {
            timer = new DispatcherTimer
            {
                Interval = TimeSpan.FromSeconds(1)
            };
            timer.Tick += Timer_Tick;
        }

        private void Timer_Tick(object sender, EventArgs e)
        {
            txtCurrentTime.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
        }

        private void UpdateWindowStatus()
        {
            if (txtWindowStatus != null)
            {
                string status = this.WindowState switch
                {
                    WindowState.Normal => "正常",
                    WindowState.Minimized => "最小化",
                    WindowState.Maximized => "最大化",
                    _ => "未知"
                };

                string topmost = this.Topmost ? " | 置頂" : "";
                txtWindowStatus.Text = $"{status}{topmost}";
            }
        }

        private void btnSendMessage_Click(object sender, RoutedEventArgs e)
        {
            string message = txtMessage.Text.Trim();
            if (string.IsNullOrEmpty(message))
            {
                MessageBox.Show("請輸入要發(fā)送的消息!", "提示",
                              MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            string fullMessage = $"[來自 {userName}]: {message}";
            DataReceived?.Invoke(this, fullMessage);

            MessageBox.Show("消息已發(fā)送到主窗口!", "成功",
                          MessageBoxButton.OK, MessageBoxImage.Information);

            txtMessage.Clear();
        }

        private void btnClearMessage_Click(object sender, RoutedEventArgs e)
        {
            txtMessage.Clear();
            txtMessage.Focus();
        }

        private void btnMinimize_Click(object sender, RoutedEventArgs e)
        {
            this.WindowState = WindowState.Minimized;
        }

        private void btnToggleTopmost_Click(object sender, RoutedEventArgs e)
        {
            this.Topmost = !this.Topmost;
            UpdateWindowStatus();

            string status = this.Topmost ? "已啟用" : "已禁用";
            MessageBox.Show($"窗口置頂功能{status}", "窗口置頂",
                          MessageBoxButton.OK, MessageBoxImage.Information);
        }

        private void btnChangePosition_Click(object sender, RoutedEventArgs e)
        {
            // 隨機(jī)改變窗口位置
            double screenWidth = SystemParameters.PrimaryScreenWidth;
            double screenHeight = SystemParameters.PrimaryScreenHeight;

            double newLeft = random.Next(0, (int)(screenWidth - this.Width));
            double newTop = random.Next(0, (int)(screenHeight - this.Height));

            this.Left = newLeft;
            this.Top = newTop;

            MessageBox.Show($"窗口已移動(dòng)到新位置\n坐標(biāo): ({newLeft:F0}, {newTop:F0})",
                          "位置變更", MessageBoxButton.OK, MessageBoxImage.Information);
        }

        private void btnClose_Click(object sender, RoutedEventArgs e)
        {
            if (MessageBox.Show("確定要關(guān)閉此窗口嗎?", "確認(rèn)關(guān)閉",
                              MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
            {
                this.Close();
            }
        }
    }
}

圖片圖片

圖片圖片

圖片圖片

開發(fā)中的常見陷阱

內(nèi)存泄漏風(fēng)險(xiǎn)

// ? 錯(cuò)誤做法:忘記移除事件訂閱
thirdWindow.DataReceived += SomeHandler;

// ? 正確做法:窗口關(guān)閉時(shí)清理資源
private void ThirdWindow_Closing(object sender, CancelEventArgs e)
{
    timer?.Stop(); // 停止定時(shí)器
    DataReceived = null; // 清理事件訂閱
}

窗口層級管理

// ? 設(shè)置父窗口,確保層級關(guān)系
secondWindow.Owner = this;

// ? 應(yīng)用關(guān)閉時(shí)清理所有子窗口
private void MainWindow_Closing(object sender, CancelEventArgs e)
{
    foreach (var window in openWindows.ToList())
    {
        if (window.IsLoaded) window.Close();
    }
}

線程安全問題

// ? UI更新必須在主線程執(zhí)行
Dispatcher.Invoke(() => {
    txtMessages.Text += $"[{DateTime.Now:HH:mm:ss}] {message}\n";
});

高級應(yīng)用場景

企業(yè)級應(yīng)用架構(gòu)

在實(shí)際項(xiàng)目中,多窗口開發(fā)常用于:

  • 模塊化設(shè)計(jì)每個(gè)功能獨(dú)立窗口
  • 權(quán)限控制根據(jù)用戶角色顯示不同窗口
  • 數(shù)據(jù)流管理窗口間的數(shù)據(jù)同步和驗(yàn)證

窗口狀態(tài)管理

// 窗口狀態(tài)持久化
publicclass WindowStateManager
{
    public static void SaveWindowState(Window window, string key)
    {
        Properties.Settings.Default[$"{key}_Left"] = window.Left;
        Properties.Settings.Default[$"{key}_Top"] = window.Top;
        Properties.Settings.Default[$"{key}_Width"] = window.Width;
        Properties.Settings.Default[$"{key}_Height"] = window.Height;
        Properties.Settings.Default.Save();
    }

    public static void RestoreWindowState(Window window, string key)
    {
        var left = Properties.Settings.Default[$"{key}_Left"];
        if (left is double leftValue) window.Left = leftValue;
        // ... 其他屬性恢復(fù)
    }
}

收藏級代碼模板

通用窗口基類

public abstract class BaseWindow : Window
{
    protected virtual void OnWindowLoaded()
    {
        this.Owner = Application.Current.MainWindow;
        this.WindowStartupLocation = WindowStartupLocation.CenterOwner;
    }

    protected virtual void OnWindowClosing()
    {
        // 子類重寫實(shí)現(xiàn)清理邏輯
    }
}

窗口管理器

public staticclass WindowManager
{
    privatestatic readonly Dictionary<Type, Window> _windows = new();

    publicstatic T ShowSingle<T>() where T : Window, new()
    {
        if (_windows.TryGetValue(typeof(T), out var existing))
        {
            existing.Activate();
            return (T)existing;
        }

        var window = new T();
        _windows[typeof(T)] = window;
        window.Closed += (s, e) => _windows.Remove(typeof(T));
        window.Show();
        return window;
    }
}

總結(jié)與展望

通過本文的完整實(shí)戰(zhàn)演示,我們掌握了WPF多窗口開發(fā)的三個(gè)核心要點(diǎn):

  1. 窗口類型選擇根據(jù)使用場景選擇模態(tài)或非模態(tài)窗口
  2. 數(shù)據(jù)通信機(jī)制構(gòu)造函數(shù)傳參、屬性返回、事件機(jī)制三種方式
  3. 資源管理策略避免內(nèi)存泄漏,正確處理窗口生命周期

掌握這些技術(shù),你就能構(gòu)建出用戶體驗(yàn)優(yōu)秀、架構(gòu)清晰的桌面應(yīng)用程序。在現(xiàn)代軟件開發(fā)中,良好的多窗口設(shè)計(jì)不僅提升了用戶體驗(yàn),更體現(xiàn)了開發(fā)者的技術(shù)水準(zhǔn)。

責(zé)任編輯:武曉燕 來源: 技術(shù)老小子
相關(guān)推薦

2025-10-31 00:17:39

2024-09-06 17:45:55

Linux磁盤

2025-10-31 07:10:00

裝飾器Python代碼

2024-06-07 08:51:50

OpenPyXLPythonExcel文件

2010-02-06 15:31:18

ibmdwAndroid

2009-07-22 14:55:16

ibmdwAndroid

2023-11-08 08:32:16

2023-05-09 08:34:51

PythonWith語句

2025-08-05 07:26:06

2025-04-11 02:30:00

2022-06-10 08:17:52

HashMap鏈表紅黑樹

2016-12-08 22:39:40

Android

2017-05-09 08:48:44

機(jī)器學(xué)習(xí)

2012-02-29 00:49:06

Linux學(xué)習(xí)

2025-02-24 10:07:10

2025-07-09 07:10:00

2010-11-08 10:20:18

2024-02-26 08:52:20

Python傳遞函數(shù)參數(shù)參數(shù)傳遞類型

2022-09-02 15:11:18

開發(fā)工具

2025-10-17 07:05:00

Python數(shù)據(jù)可視化數(shù)據(jù)科學(xué)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

人妻激情偷乱频一区二区三区| 国产亚洲欧美一区二区三区| 日本中文在线视频| 在线观看视频一区二区三区| 午夜精品免费在线观看| 日韩av在线电影观看| 国产三级小视频| 国产一区导航| 久久午夜a级毛片| 国产麻豆天美果冻无码视频| 综合久草视频| 日韩欧美国产骚| 在线观看国产一区| 三级在线播放| 国产一区二区精品久久91| 欧美影院久久久| www.黄色com| 亚洲伊人春色| 精品欧美一区二区在线观看| 欧美自拍小视频| 高端美女服务在线视频播放| 亚洲欧洲三级电影| 欧美精品一区二区视频 | 亚洲国产第一| 日韩中文字幕免费看| 国产一级二级在线观看| 日韩精品一区二区三区中文| 91久久精品一区二区| 欧美狂野激情性xxxx在线观| 午夜伦全在线观看| 国产亚洲欧洲一区高清在线观看| 翡翠波斯猫1977年美国| 国产精品女人久久久| 日韩二区三区四区| 欧美在线播放视频| xxxxxx国产| 欧美欧美全黄| 欧美激情a在线| www.99re7| 久久影院一区| 神马久久桃色视频| 欧美大波大乳巨大乳| 任我爽精品视频在线播放| 精品国产一二三| 中国特级黄色片| 日韩中文一区二区| 欧美一级淫片007| 久久精品一二三四| 精品中文字幕一区二区三区| 欧美日韩黄色影视| 日本肉体xxxx裸体xxx免费| 666av成人影院在线观看| 色老汉av一区二区三区| 国产福利一区视频| 国产成人精品一区二三区在线观看| 欧美性xxxx18| 又色又爽又高潮免费视频国产| sis001亚洲原创区| 五月激情综合婷婷| 日本精品免费在线观看| 亚洲同志男男gay1069网站| 欧美日韩一二三四五区| 东京热加勒比无码少妇| 日韩国产网站| 欧美日韩国产综合视频在线观看| 亚洲 激情 在线| 国产95亚洲| 欧美不卡视频一区| 欧美肉大捧一进一出免费视频| 开心激情综合| 亚洲欧美日韩天堂一区二区| 日本欧美一区二区三区不卡视频| 日韩片欧美片| 久久6精品影院| 日本视频www| 日韩激情一二三区| 成人美女免费网站视频| 性生交生活影碟片| 26uuu国产在线精品一区二区| 日本免费高清不卡| 乱人伦中文视频在线| 亚洲在线视频网站| 无码无遮挡又大又爽又黄的视频| 天堂久久一区| 亚洲电影免费观看高清完整版在线观看 | 国产视频九色蝌蚪| 成人a在线观看高清电影| 91精品国产综合久久小美女| 91精品又粗又猛又爽| 国产精品羞羞答答在线观看| 久久亚洲精品国产亚洲老地址| 欧美日韩中文视频| 视频在线在亚洲| 亚洲最大福利视频网| 图片区 小说区 区 亚洲五月| 中文字幕不卡在线播放| 国产尤物av一区二区三区| 自拍网站在线观看| 欧美一级片在线看| 欧美成人午夜精品免费| 亚洲精品一区二区在线看| 777精品视频| 国产三级精品在线观看| 久久久美女艺术照精彩视频福利播放| 欧美日韩视频免费在线观看| 日韩在线伦理| 日韩免费高清视频| 免费成人深夜天涯网站| 国产美女一区| 51精品国产人成在线观看| 粉嫩一区二区三区国产精品| 亚洲第一狼人社区| 亚洲免费黄色录像| 久草精品在线| 欧美激情久久久久久| 亚洲天堂自拍偷拍| 久久亚洲一区二区三区四区| av在线观看地址| 日本免费成人| 亚洲性猛交xxxxwww| 五月天婷婷丁香| 精品午夜久久福利影院| 日本精品一区二区三区高清 久久| missav|免费高清av在线看| 91麻豆精品91久久久久久清纯| 99久久人妻无码精品系列| 亚洲成人中文| 99久久精品免费看国产四区 | 欧美高跟鞋交xxxxxhd| 中文字幕在线一| 久久久精品国产免费观看同学| 欧美一级视频免费看| 亚洲日本视频在线| 欧美成人午夜剧场免费观看| 亚洲无码精品在线播放| 中文成人综合网| 欧美综合在线观看视频| 欧美a一欧美| 国内精品久久久久影院优 | 成人免费看片98欧美| 国产成a人无v码亚洲福利| 91九色国产ts另类人妖| 99er精品视频| 久久精品国产99国产精品澳门| 做爰视频毛片视频| 中文字幕巨乱亚洲| 日韩爱爱小视频| 久久一区二区中文字幕| 国产一区二区视频在线观看| 日本www在线| 91精品国产一区二区人妖| 国产精品成人69xxx免费视频| 久久99精品国产麻豆不卡| 亚洲v国产v| 男女啪啪999亚洲精品| 色婷婷av一区二区三区在线观看| 中文字幕免费播放| 中文字幕中文乱码欧美一区二区| 九九热免费在线观看| 91日韩视频| 91精品婷婷国产综合久久蝌蚪| 91精品久久| 精品粉嫩aⅴ一区二区三区四区| 国产真实夫妇交换视频 | 91麻豆精品久久毛片一级| 美国毛片一区二区三区| 中文字幕不卡每日更新1区2区| 经典三级久久| 久久久女女女女999久久| 熟妇高潮一区二区三区| 色婷婷久久久久swag精品| www久久久久久久| 国产一区91精品张津瑜| 丝袜人妻一区二区三区| 国产一区二区区别| 91精品视频免费观看| 超黄网站在线观看| 国产视频亚洲精品| 一卡二卡三卡在线观看| 亚洲一线二线三线久久久| 精品国产av无码| 国内一区二区在线| 国产白丝袜美女久久久久| 菠萝蜜一区二区| 产国精品偷在线| **在线精品| 九九久久久久99精品| 你懂的在线观看视频网站| 欧美精品1区2区3区| www成人在线| 综合在线观看色| 97人妻精品一区二区三区免 | 91网站免费看| 中文不卡1区2区3区| 久久这里有精品视频| 欧美色18zzzzxxxxx| 欧美一级夜夜爽| 精品乱码一区内射人妻无码| 亚洲一区二区三区四区在线观看| 调教驯服丰满美艳麻麻在线视频| 成人精品国产福利| 亚洲36d大奶网| 亚洲看片免费| 国产女主播一区二区| www在线观看黄色| 久久久精品国产一区二区| 婷婷丁香花五月天| 欧美三级日韩在线| 精品久久免费视频| 欧美国产精品v| 国产综合内射日韩久| 久久99国产精品免费网站| aa视频在线播放| 成人嫩草影院| 久久国产精品免费一区| 伊人亚洲精品| 97碰在线观看| 日韩成人伦理| 最近的2019中文字幕免费一页| 日本成人动漫在线观看| 91精品国模一区二区三区| 免费视频久久久| 亚洲观看高清完整版在线观看| av男人的天堂av| 99视频在线观看一区三区| 国产成人美女视频| 麻豆精品网站| 国产91沈先生在线播放| 91青青国产在线观看精品| 欧美一区二区综合| 日本国产精品| 久久精品中文字幕一区二区三区| 日韩区欧美区| 成人黄色大片在线免费观看| 午夜精品久久久久久久久久蜜桃| 国内精品一区二区三区| 黄色网址视频在线观看| 亚洲无线码在线一区观看| 日本五码在线| 亚洲国产美女久久久久| av免费在线不卡| 欧美性一区二区| 中国女人一级一次看片| 色成人在线视频| 69成人免费视频| 欧美视频中文字幕在线| 日韩欧美视频在线免费观看| 亚洲成av人片在www色猫咪| 亚洲欧美另类日本| 亚洲三级小视频| 免费成人美女女在线观看| 国产欧美日韩中文久久| 日本猛少妇色xxxxx免费网站| 久久精品欧美一区二区三区不卡| jizz日本免费| 91麻豆高清视频| 人与嘼交av免费| 日本一区二区三区久久久久久久久不| 婷婷色一区二区三区| 国产精品丝袜一区| 亚洲一区 欧美| 国产精品久久久久四虎| 天天操夜夜操av| 一区二区三区在线视频免费| 久草视频在线免费看| 亚洲一区二区三区小说| 久久久久女人精品毛片九一| 日本韩国一区二区| 中文字幕永久免费视频| 在线播放日韩导航| 国产日韩欧美视频在线观看| 欧美大片在线观看| 欧洲av在线播放| 亚洲视频欧洲视频| 日本综合在线| 欧美成人午夜激情视频| 625成人欧美午夜电影| 国产经典一区二区| 羞羞视频在线观看一区二区| 91欧美精品成人综合在线观看| 我要色综合中文字幕| 九九九久久久| 日韩欧美一区二区三区免费看| 屁屁影院ccyy国产第一页| 亚洲精品九九| 免费看a级黄色片| 国产suv精品一区二区三区| 亚洲精品女人久久久| 国产精品网站在线播放| 国产亚洲成人精品| 日本道免费精品一区二区三区| 中文字幕一区二区三区人妻四季| 精品国产一区久久| 免费黄色在线视频网站| 久久精品国产视频| 国产视频一区二区| 日韩av电影在线播放| 96sao精品免费视频观看| 国产有色视频色综合| 91精品精品| 欧美日韩激情视频在线观看| 久久精品国产77777蜜臀| 人妻无码一区二区三区| 中文字幕一区二区三区在线观看| 国产精品30p| 91精品婷婷国产综合久久| 免费播放片a高清在线观看| 久久久精品2019中文字幕神马| 91精品韩国| 国产精品手机在线| 99久久99久久精品国产片桃花| 亚洲中文字幕无码中文字| 黄色小说综合网站| 黄色短视频在线观看| 亚洲va韩国va欧美va| 亚洲性生活大片| 日韩av在线免费看| bbw在线视频| 91精品在线观看视频| 久久99免费视频| 精品国产免费av| 国产精品1区二区.| 999久久久国产| 欧美在线观看禁18| 天堂网2014av| 欧美日韩高清区| 麻豆精品在线| 先锋影音一区二区三区| 亚久久调教视频| 欧美亚一区二区三区| 亚洲国产精品久久久久婷婷884| 91tv国产成人福利| 日韩在线观看免费网站| 午夜欧美巨大性欧美巨大| 国产伦视频一区二区三区| 韩日欧美一区| 杨幂一区二区国产精品| 亚洲欧美综合色| 国产女人爽到高潮a毛片| 中文字幕在线国产精品| 亚洲最大网站| 清纯唯美一区二区三区| 性欧美xxxx大乳国产app| 免费看黄色aaaaaa 片| 午夜不卡av免费| 日本免费网站在线观看| 97视频在线观看免费高清完整版在线观看 | 国内精品久久久久久| 中文字幕亚洲在线观看| 女同性恋一区二区| 国产福利一区在线观看| avtt天堂在线| 日韩一区二区三区视频在线| 人交獸av完整版在线观看| 99久re热视频这里只有精品6| 欧美a级在线| 亚洲高清无码久久| 亚洲成av人片一区二区三区| 天堂在线视频网站| 日本免费久久高清视频| 欧美美乳视频| 成人在线看视频| 国产精品素人一区二区| 国产精品久久影视| 欧美国产精品日韩| 国产精品一区二区中文字幕| 九一国产精品视频| 久久精品视频免费| 中文在线字幕av| 久久香蕉国产线看观看av| 美女福利一区| 88av.com| 国产精品你懂的在线欣赏| 国产精品嫩草影院桃色| 久久久久久久国产精品视频| 香蕉国产成人午夜av影院| 亚洲xxxx2d动漫1| 亚洲桃色在线一区| 少妇无码一区二区三区| 日本精品一区二区三区在线播放视频| 午夜a一级毛片亚洲欧洲| 亚洲xxx在线观看| 亚洲综合色噜噜狠狠| 加勒比一区二区三区在线| 国产美女精品视频免费观看| 欧美成人日韩| 欧美人妻一区二区三区| 正在播放亚洲一区| yellow在线观看网址| 日韩中文字幕av在线| 国产一区二区在线免费观看| 91精品国产乱码在线观看| 宅男66日本亚洲欧美视频| 一区二区三区伦理片| 日韩av不卡一区二区| 天天看片中文字幕| 一区二区福利视频| 日韩视频一二区| 草草久久久无码国产专区| 中文字幕制服丝袜一区二区三区|