【问题标题】:XAML - Update text on different property updateXAML - 更新不同属性更新的文本
【发布时间】:2016-02-24 10:03:28
【问题描述】:

所以我有以下 XAML:

<TextBlock Text="{Binding DisconnectedDevices, UpdateSourceTrigger=PropertyChanged}" />

视图模型具有以下属性:

public string DisconnectedDevices {get; set;}
public IEnumerable<IDeviceInformationVM> DeviceCollection {get; set;}

有一个被调用的方法会引发属性通知事件:

public void DeviceCollectionChanged()
{
    RaisePropertyChanged(() => DeviceCollection);
}

我想在 DeviceCollection 更改时更新 TextBlock 中的值。我知道我可以在 DisconnectedDevices 上调用 RaisePropertyChanged,但我想知道是否可以在不同的属性更改事件上更新 TextBlock。

谢谢大家!

编辑:感谢您提出使用 ObservableCollection 而不是 IEnumerable 的建议,不幸的是,我无权更改集合类型..

只要集合发生变化,就会调用 DeviceCollectionChanged 方法(我知道这很乏味...)

进一步编辑: 刚刚开始

RaisePropertyChanged(() => DisconnectedDevices);

我很感激问题中可能没有提供足够的信息来了解我想要做的事情,对此表示歉意

【问题讨论】:

  • 这个问题没有意义。在 DisconnectedDevices 属性上调用 RaisePropertyChanged,这就是 INotifyPropertyChanged 的​​发明目的。除此之外,从绑定中删除UpdateSourceTrigger=PropertyChanged。这是多余的,因为 TextBlock 从不主动更改其 Text 属性。
  • @Clemens 关于 UpdateSourceTrigger 的默认值并不总是正确的。对于文本,它可能是 LostFocus msdn.microsoft.com/en-us/library/…
  • @chameleon86 仅当我们讨论双向绑定时才适用,即可以更改其 Text 属性的控件(例如,通过像 TextBox 这样的用户输入)。这里我们有一个 TextBlock,它永远不会改变它的 Text 属性,即单向绑定。此绑定的源属性永远不会由绑定设置,因此 UpdateSourceTrigger 完全是多余的。

标签: c# wpf xaml


【解决方案1】:

我不确定您当前的代码是否有效,但假设它有效。 为什么不使用 - ObservableCollection&lt;IDeviceInformationVM&gt; 而不是 IEnumerable&lt;IDeviceInformationVM&gt; DeviceCollection 你不需要 DeviceCollectionChanged 事件。它会得到照顾。

是的,你可以加注

public void DeviceCollectionChanged()
{
    RaisePropertyChanged(() => DeviceCollection);
    RaisePropertyChanged(() => DisconnectedDevices);
   // or RaisePropertyChanged("DisconnectedDevices"); Whichever works
}

看到这个问题,它可能会帮助您实现多个属性的 NotifyPropertyChanged - WPF Notify PropertyChanged for a Get Property

【讨论】:

    【解决方案2】:

    是否每次更改 DeviceCollection 时都调用 DeviceCollectionChanged() 方法?如何设置 DeviceCollection?

    您可以实现 ObservableCollection(this 答案的底部),或者根据您设置 DeviceCollection 的方式,例如,如果 DeviceCollection 来自列表,您可以实现如下所示:

    private IEnumerable<IDeviceInformationVM> deviceCollection;
    public IEnumerable<IDeviceInformationVM> DeviceCollection 
    {
     get
      {
        return deviceCollection;
      }
      set
      {
        deviceCollection = value; 
        RaisePropertyChanged(() => DisconnectedDevices);
        RaisePropertyChanged(() => DeviceCollection);
      }
    }
    
    DeviceCollection = GetListOfIDeviceInformationVM(); //will automatically raise property changed and update your TextBlock
    

    您不必一直打电话给RaisePropertyChanged(),这看起来很乏味

    【讨论】:

      【解决方案3】:

      将 CollectionDevice 集合的类型更改为 ObservableCollection 然后引发事件 CollectionChanged 如下: DeviceCollection.CollectionChanged + = DeviceCollection_CollectionChanged; 我在 MVVM 中给你一个 RelayCommand 类的实现

      这里是视图:(MainView)

      <Window x:Class="WpfApplication.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:WpfApplication"
          mc:Ignorable="d"
          Title="MainWindow" Height="350" Width="525">
      
      <Window.DataContext>
          <local:MainViewModel/>
      </Window.DataContext>
      
      <Grid>
          <Grid.RowDefinitions>
              <RowDefinition Height="*"/>
              <RowDefinition Height="*"/>
          </Grid.RowDefinitions>
      
          <TextBlock Text="{Binding DisconnectedDevices, Mode=TwoWay}" Height="25" Width="175" Grid.Row="0" />
          <Button Grid.Row="1" Content="Click" Command="{Binding ToggleExecuteCommand}"  Width="100" Height="25"/>
      
      </Grid>
      

      ViewModel(主视图模型)

          using System;
      using System.Collections.ObjectModel;
      using System.Collections.Specialized;
      using System.ComponentModel;
      
      namespace WpfApplication
      {
          public class MainViewModel : INotifyPropertyChanged
          {
              private string disconnectedDevices;
      
              public event PropertyChangedEventHandler PropertyChanged;
      
              private void NotifyPropertyChanged(String info)
              {
                  if (PropertyChanged != null)
                  {
                      PropertyChanged(this, new PropertyChangedEventArgs(info));
                  }
              }
      
              public MainViewModel()
              {
                  ToggleExecuteCommand = new RelayCommand(ChangeCollection);
                  DeviceCollection = new ObservableCollection<DeviceInformationVM>();
                  DeviceCollection.CollectionChanged += DeviceCollection_CollectionChanged;
              }
      
              private void ChangeCollection(object obj)
              {
                  DeviceCollection.Add(new DeviceInformationVM { MyProperty = "TEST" });
              }
      
              private void DeviceCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
              {
                  NotifyCollectionChangedAction action = e.Action;
      
                  if (action == NotifyCollectionChangedAction.Add)
                  {
                      DisconnectedDevices = "Somme thing added to collection";
                  }
      
                  if (action == NotifyCollectionChangedAction.Remove)
                  {
                      DisconnectedDevices = "Somme thing removed from collection";
                  }
              }
      
              public string DisconnectedDevices
              {
                  get { return this.disconnectedDevices; }
      
                  set
                  {
                      if (value != this.disconnectedDevices)
                      {
                          this.disconnectedDevices = value;
                          NotifyPropertyChanged("DisconnectedDevices");
                      }
                  }
              }
      
              public ObservableCollection<DeviceInformationVM> DeviceCollection { get; set; }
      
              public RelayCommand ToggleExecuteCommand { get; set; }
      
          }
      }
      

      中继命令:

      using System;
      

      使用 System.Windows.Input;

      命名空间 WpfApplication { 公共类 RelayCommand : ICommand { 私有动作执行;

          private Predicate<object> canExecute;
      
          private event EventHandler CanExecuteChangedInternal;
      
          public RelayCommand(Action<object> execute)
              : this(execute, DefaultCanExecute)
          {
          }
      
          public RelayCommand(Action<object> execute, Predicate<object> canExecute)
          {
              if (execute == null)
              {
                  throw new ArgumentNullException("execute");
              }
      
              if (canExecute == null)
              {
                  throw new ArgumentNullException("canExecute");
              }
      
              this.execute = execute;
              this.canExecute = canExecute;
          }
      
          public event EventHandler CanExecuteChanged
          {
              add
              {
                  CommandManager.RequerySuggested += value;
                  this.CanExecuteChangedInternal += value;
              }
      
              remove
              {
                  CommandManager.RequerySuggested -= value;
                  this.CanExecuteChangedInternal -= value;
              }
          }
      
          public bool CanExecute(object parameter)
          {
              return this.canExecute != null && this.canExecute(parameter);
          }
      
          public void Execute(object parameter)
          {
              this.execute(parameter);
          }
      
          public void OnCanExecuteChanged()
          {
              EventHandler handler = this.CanExecuteChangedInternal;
              if (handler != null)
              {
                  handler.Invoke(this, EventArgs.Empty);
              }
          }
      
          public void Destroy()
          {
              this.canExecute = _ => false;
              this.execute = _ => { return; };
          }
      
          private static bool DefaultCanExecute(object parameter)
          {
              return true;
          }
      }
      

      }

      最后是设备信息

          using System;
      
      namespace WpfApplication
      {
          public interface IDeviceInformationVM
          {
              string MyProperty { get; set; }
          }
      
          public class DeviceInformationVM : IDeviceInformationVM
          {
              public string MyProperty
              {
                  get; set;
              }
          }
      }
      

      希望对你有帮助

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-08-10
        • 1970-01-01
        • 2016-08-07
        • 1970-01-01
        • 1970-01-01
        • 2011-11-03
        • 1970-01-01
        相关资源
        最近更新 更多