簡體   English   中英

如何在WPF中從一個窗口計數到另一個窗口

[英]How can I get count in one window to another in wpf

在我的代碼中,我獲得了第二個窗口中的點擊計數,並在第一個窗口即主窗口中顯示了該怎么辦。 我在下面嘗試的方法不起作用

    C# code in second window

 public partial class Window1 : Window
    {
        int counter = 0;

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            counter++;
            hope.Text = counter.ToString();
        }
    }
    Xaml code in Main window
  <TextBlock x:Name="hope" HorizontalAlignment="Left" TextWrapping="Wrap"   FontWeight="Bold" Text="Attendees" VerticalAlignment="Top" Height="23" Width="157"/>

您的代碼無法正常工作,因為TextBox hope被定義為主類中的一個字段,並且您試圖在第二個類中引用它而不指定第一個類的實例。 有幾種方法來解決這個問題(你可能暴露參考, hope作為一個公共靜態變量),但你絕對應該考慮實現MVVM。 我建議您查找有關它的詳細教程,以便獲得完整的故事,但是在這里我將嘗試解釋其基本知識。

遵循MVVM(模型-視圖-視圖模型)時,將代碼划分為幾個離散的角色。 XAML和任何相關的背后代碼均被視為視圖角色的一部分。 問題中的代碼示例也是視圖的一部分。 通常,您希望視圖在嚴格必需的范圍內或與UI直接相關的范圍之外實現任何邏輯。 此規則有例外,但通常應遵循該規則。

視圖模型的工作是促進模型(數據)與視圖之間的通信。 例如,您可以將計數器變量放入數據庫中,或將其打包為可序列化的類,然后從文件中加載它。 viewmodel將通過公共屬性訪問您選擇的任何模型,該模型的set和get函數將確保正確訪問數據。

最后,視圖可以通過綁定到視圖模型上的屬性來訪問計數器。 綁定非常好,因為它允許視圖在屬性更改時自動更新 但是,要使其正常工作,您將需要使您的視圖模型實現INotifyPropertyChanged ,該方法會通知WPF組件它們需要顯示不同的值。

運作方式如下:

  1. 視圖模型上的值已更改。
  2. 修改后的屬性引發PropertyChanged事件。
  3. 綁定到該屬性的所有組件都將處理該事件並更新其值。

最后,要從視圖更改視圖模型上的屬性,可以使用命令 命令是在視圖模型上實現的,可以從視圖中執行。 在許多情況下,可以使用命令代替事件。

我編寫了一個簡單的計數器程序,該程序演示了一些MVVM核心原理。 它所要做的就是在單擊按鈕時增加一個數字,類似於示例代碼。 它在一個窗口中,但是您可以輕松地對其進行修改以與兩個不同的窗口一起使用。 我建議嘗試做為練習,這樣您就可以了解一切的工作原理。

如果您使用的是Visual Studio,則可以將所有這些內容復制粘貼到名為“ ExampleProject”的WPF項目中並運行它; 我測試了它,並且按預期工作。

XAML:

<Window x:Class="ExampleProject.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:ExampleProject"
        xmlns:viewmodel="clr-namespace:ExampleProject.ViewModel"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">

    <!-- we reference our CounterViewModel class via XAML here. note that to access it, 
    we need to specify the namespace it's in by adding 
    xmlns:viewmodel="clr-namespace:ExampleProject.ViewModel"-->
    <Window.Resources>
        <viewmodel:CounterViewModel x:Key="Counter"></viewmodel:CounterViewModel>
    </Window.Resources>

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

        <!-- here we bind to the Counter property in the viewmodel. we reference it in 
        XAML via the value assigned to x:Key (in this case, Counter). the value assigned
        to the "Source" parameter tells WPF where to look for properties. the value
        assigned to Path tells it which property to bind to.-->
        <TextBlock Grid.Row="0" 
                   Text="{Binding Source={StaticResource Counter}, Path=Counter}" 
                   FontSize="50" 
                   HorizontalAlignment="Center" 
                   VerticalAlignment="Center"/>

        <Button Grid.Row="1" 
                Content="Press Me" 
                Command="{Binding Source={StaticResource Counter}, Path=Increment}"
                CommandParameter="{StaticResource Counter}"
                FontSize="60"></Button>
    </Grid>
</Window>

視圖模型:

using System.ComponentModel;
using System.Windows.Input;
using ExampleProject.Commands;
using ExampleProject.Model;

namespace ExampleProject.ViewModel
{
    //this is the viewmodel. note that it implements INotifyPropertyChanged.
    //you almost always want your viewmodel to do so.
    public class CounterViewModel : INotifyPropertyChanged
    {
        //invoke this whenever you change a property that your controls 
        //might be binding to
        public event PropertyChangedEventHandler PropertyChanged;

        //this is the underlying data. including a reference to the model in
        //your viewmodel is one way to facilitate communication between the 
        //two, although there are other ways.
        private CounterModel model;

        //this is the most important part; your view will bind to this.
        public int Counter
        {
            get { return model.Counter; }
            set
            {
                model.Counter = value;
                PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Counter"));
            }
        }

        //this is a function that will increment the counter and can be called
        //directly from XAML.
        public ICommand Increment { get; }

        //this constructor needs to be parameterless in our case, because
        //we will be creating an instance of this class from XAML.
        public CounterViewModel()
        {
            model = new CounterModel(0);
            Increment = new IncrementCommand();
        }
    }
}

模型:

namespace ExampleProject.Model
{
    //this is a simple model class. generally, you don't want to
    //implement any logic here; in pure MVVM the model just 
    //encapsulates raw data. 
    public class CounterModel
    {
        public int Counter;

        public CounterModel(int counterValue)
        {
            Counter = counterValue;
        }
    }
}

遞增命令:

using System;
using System.Windows.Input;
using ExampleProject.ViewModel;

namespace ExampleProject.Commands
{
    public class IncrementCommand : ICommand
    {
        //necessary to implement because of ICommand but we're not currently using this
        public event EventHandler CanExecuteChanged;

        public bool CanExecute(object parameter)
        {
            //if this method returns false, the command won't be executed.
            return true;
        }

        public void Execute(object parameter)
        {
            //parameter is passed in via XAML; it's always an instance of CounterViewModel
            //but i double-check what kind of object it is anyway.
            if (parameter is CounterViewModel viewModel)
            {
                viewModel.Counter++;
            }
        }
    }
}

請注意,我不需要在背后的代碼中添加任何內容。 這並非總是可能的,但是如果可以管理它通常是一件好事。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM