XAML INotifyPropertyChanged для обновления пользовательского интерфейса

Я новичок в XAML и пытаюсь найти лучший способ сделать это. Я заметил, что пользовательский интерфейс не обновляется сразу после изменения кода.

Я хочу использовать интерфейс INotifyPropertyChanged, чтобы GUI уведомлялся об изменениях и обновлениях.

Изначально в XAML я установил для видимости значение hidden (для TextBlock или изображения) или true (isCheck или isEnabled).

Во время программы в коде позади я устанавливаю значение visible или false.

Но GUI не обновляется. Ниже приведена структура, которая у меня есть для страницы. Все свойства изменяются (становятся видимыми) при нажатии кнопки.

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

Прямо сейчас я использую UpdateGUI() после внесения изменений для обновления пользовательского интерфейса. ОбновитьGUI();

public void UpdateUI()
{
    //remove this function from the code below.
    Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new ThreadStart(delegate { }));
}

MainWindow.xaml

    <Grid Margin=" 0, 20, 0, 0">
        <StackPanel Margin="20, 0, 0, 0">
            <StackPanel Orientation="Horizontal" >
                <Image x:Name="CheckBox1Img" Margin="0, 2, 0, 0" Source="{StaticResource doneCheckImage}" Visibility="Hidden"/>
                <CheckBox x:Name="Checkbox1" Content="CheckBox1"/>
            </StackPanel>

            <StackPanel Orientation="Horizontal">
                <Image x:Name="CheckBox2Img" Margin="0, 2, 0, 0" Source="{StaticResource doneCheckImage}" Visibility="Hidden"/>
                <CheckBox x:Name="Checkbox2" Content="CheckBox 2"/>
            </StackPanel>

            <StackPanel Orientation="Horizontal">
                <Image x:Name="CheckBox3Img" Margin="0, 2, 0, 0" Source="{StaticResource doneCheckImage}" Visibility="Hidden"/>
                <CheckBox x:Name="CheckBox3"  Content="CheckBox 3"/>
            </StackPanel>

            <Button x:Name="Button1"  Click="Button1_Click" Height="20"  Content="Click" Width="50"/>
            <Button x:Name="Button2"  Click="Button2_Click" Height="20"  Content="Button to disable" Width="200"/>
        </StackPanel>
    </Grid>

MainWindow.cs

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Button1_Click(object sender, RoutedEventArgs e)
        {
            Checkbox1.IsEnabled = false;
            Checkbox2.IsEnabled = false;
            Checkbox3.IsEnabled = false;
            CheckBox1Img.Visibility = Visibility.Visible;
            CheckBox2Img.Visibility = Visibility.Visible;
            CheckBox3Img.Visibility = Visibility.Visible;

            Button2.IsEnabled = false;
        }

        private void Button2_Click(object sender, RoutedEventArgs e)
        {

        }

App.XAML

<Application.Resources>
    <!-- Blue Check Image -->
    <BitmapImage x:Key="doneCheckImage" UriSource="blueCheck.png" />
</Application.Resources>

person Imsa    schedule 09.04.2016    source источник
comment
Вы изучали шаблон MVVM? Как вы вызываете функцию UpdateUI?   -  person Firoz    schedule 09.04.2016
comment
Установка свойств элементов управления из кода позади должна быть корректной, элементы управления должны обновляться немедленно.   -  person slugster    schedule 09.04.2016


Ответы (1)


  1. Добавьте модель представления (простой класс .cs) в новую папку ViewModels.
  2. Реализуйте интерфейс INotifyPropertyChanged следующим образом:

     public class ViewModel:INotifyPropertyChanged{
     //Example for a valid INotifyPropertyChanged member
     private bool _visibility;
    
     public bool Visibility
    {
        get { return _visibility; }
        set { _visibility = value;  OnPropertyChanged("Visibility");}
    }
     public event PropertyChangedEventHandler PropertyChanged;
     private void OnPropertyChanged(string propertyName){
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                }
            }
    }
    

Теперь создайте новый класс .cs — назовите его как-нибудь вроде BooleanToVisibilityConverter.cs:

Код должен выглядеть примерно так:

 public class BooleanToVisibilityConverter : IValueConverter
{
    object IValueConverter.Convert(object value, Type targetType, object parameter, string language)
    {
        if((bool)value == true)
        {
            return Visibility.Visible;
        }
        else
        {
            return Visibility.Collapsed;
        }
    }

    object IValueConverter.ConvertBack(object value, Type targetType, object parameter, string language)
    {
        throw new NotImplementedException();
    }
}

Теперь перейдите в свой xaml, где вы хотите привязать эту модель представления, добавьте это после тега <page — Intellisense поможет вам, если вы просто наберете ViewModel:

xmlns:vm ="using:APPLICATIONNAME.ViewModels"  

Далее добавьте в свой xaml:

  <Page.Resources>
    <vm:ViewModel x:Key="MyVM"></vm:ViewModel>
</Page.Resources>

Теперь создайте свой проект, а затем выберите в xaml элемент пользовательского интерфейса, к которому вы хотите привязать свои данные. Затем откройте окно свойств элемента пользовательского интерфейса и найдите «Видимость»; щелкните квадрат и нажмите «Создать привязку данных», выберите «Статический ресурс» и установите преобразователь значений в BooleanToVisibilityConverter.

введите здесь описание изображения

Вы можете получить доступ к своей модели представления в С#, установив контекст данных в xaml. Возможно, вы захотите сначала глубоко изучить теорию mvvm.

person Matthias Herrmann    schedule 10.04.2016