Как я могу получить счет в одном окне к другому в wpf - PullRequest
1 голос
/ 30 мая 2019

В моем коде я получаю количество кликов во втором окне и показываю его в первом окне, которое является главным окном. Как я могу это сделать. То, что я попробовал ниже, не работает

    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"/>

1 Ответ

2 голосов
/ 31 мая 2019

Ваш код не работает, потому что TextBox hope определен как поле в вашем основном классе, и вы пытаетесь сослаться на него во втором классе, не указывая экземпляр вашего first класса , Есть несколько способов обойти это (вы могли бы выставить ссылку на hope в качестве публичной статической переменной), но вам определенно стоит взглянуть на реализацию MVVM. Я рекомендую поискать подробное руководство по нему, чтобы вы могли получить полную историю, но я попытаюсь объяснить основы здесь.

Следуя MVVM (модель-представление-представление-модель), вы делите код на несколько отдельных ролей. XAML и любой связанный с ним кодовый компонент считаются частью роли представления. Примеры кода в вашем вопросе также являются частью представления. В общем, вы , а не хотите, чтобы представление реализовало любую логику за пределами того, что строго необходимо или связано непосредственно с пользовательским интерфейсом. Есть исключения из этого правила, но в целом вы должны следовать ему.

Задача модели представления заключается в облегчении связи между вашей моделью (данными) и вашим представлением. Например, вы можете поместить переменную counter в базу данных или упаковать ее в сериализуемый класс и загрузить из файла. Модель представления будет обращаться к любой модели, которую вы выберете, через открытое свойство, чьи функции set и get обеспечат правильный доступ к данным.

Наконец, представление может получить доступ к счетчику, связавшись со свойством в модели представления. Привязка действительно хороша, потому что она позволяет автоматически обновлять при изменении свойства. Однако, чтобы это работало, вам нужно, чтобы ваш viewmodel реализовал INotifyPropertyChanged, который уведомляет ваши компоненты WPF о том, что им нужно отображать другое значение.

Вот как это работает:

  1. Значение в модели просмотра изменено.
  2. Свойство, которое было изменено, вызывает событие PropertyChanged.
  3. Любые компоненты, связанные со свойством, обрабатывают событие и обновляют свое значение.

Наконец, чтобы изменить свойство модели представления из представления, вы можете использовать команды . Команды реализованы в модели представления и могут быть выполнены из представления. Команды могут использоваться вместо событий при многих обстоятельствах.

Я написал простую счетную программу, которая демонстрирует несколько основных принципов MVVM. Все, что он делает, это увеличивает число, когда вы нажимаете на кнопку, аналогично вашему примеру кода. Это в одном окне, но вы можете легко изменить его для работы с двумя разными. Я рекомендую попробовать сделать это как упражнение, чтобы вы могли почувствовать, как все работает.

Если вы используете Visual Studio, вы можете скопировать и вставить все это в проект WPF с именем «ExampleProject» и запустить его; Я проверил это, и он работает как ожидалось.

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>

ViewModel:

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++;
            }
        }
    }
}

Обратите внимание, что мне не нужно ничего добавлять к коду. Это не всегда возможно, но часто это хорошо, когда вы можете управлять этим.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...