RaisePropertyChanged在不同属性上触发“设置”

时间:2018-09-24 15:29:05

标签: c# wpf mvvm mvvm-light

当我遇到一个我似乎无法弄清的MVVM Light中的RaisePropertyChanged问题时,我正在一个项目上。当我尝试对列表进行更改时,列表确实会更新,但是上面选择的索引值也会更新。传递给我选择的索引的值似乎受按下哪个键触发事件的影响(即,如果我按“ BACKSPACE”,则传递给设置器的值是“ -1”,而如果输入字母,传递的值为“ 0”)

我重新创建了一个纯粹演示该问题的项目。以下是MainVeiwModel中发现的主要逻辑部分:

public class MainViewModel : ViewModelBase
{
    public MainViewModel()
    {
        _testItems = new List<TestItem>()
        {
            new TestItem() { Name = "Test1" },
            new TestItem() { Name = "Test2" }
        };
    }

    public int SelectedIndex
    {
        get { return _selectedIndex; }
        set
        {
            _selectedIndex = value;
            RaisePropertyChanged("SelectedIndex");
            RaisePropertyChanged("SelectedText");
            RaisePropertyChanged("TestList");
        }
    }

    public string SelectedText
    {
        get
        {
            return _testItems[_selectedIndex].Name;
        }
        set
        {
            _testItems[_selectedIndex].Name = value;
            RaisePropertyChanged("TextList");
        }
    }

    public List<string> TextList
    {
        get
        {
            _textList = new List<string>();
            if (_testItems != null && _testItems.Count > 0)
            {
                foreach (TestItem item in _testItems)
                    _textList.Add(item.Name);
            }
            return _textList;
        }
        set { _textList = value; }
    }

    private int _selectedIndex;
    private List<string> _textList;
    private List<TestItem> _testItems;
}

我的XAML:

<Window x:Class="RaisePropertyBug.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:RaisePropertyBug"
    mc:Ignorable="d"
    DataContext="{Binding Source={StaticResource Locator}, Path=Main}"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="*" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>

    <ComboBox ItemsSource="{Binding TextList, UpdateSourceTrigger=PropertyChanged}"
              SelectedIndex="{Binding SelectedIndex, UpdateSourceTrigger=PropertyChanged}"
        HorizontalAlignment="Center" VerticalAlignment="Center"/>

    <TextBox Grid.Row="1" Text="{Binding SelectedText, UpdateSourceTrigger=PropertyChanged}"
        HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>

对于上下文:我有一个ComboBox,其中列出了我所拥有的项目集合中的名称。有一个编辑窗口,用户可以在其中更改这些项目的名称和其他属性。我的目标是在用户编辑值时更新ComboBox列表。在我的实际程序中,您可以使用索引0处的项目执行此操作,但是只要按下一个键并到达RaisePropertyChanged()区域,任何其他索引就会自动更改为0。

2 个答案:

答案 0 :(得分:0)

检查下面的代码是否符合您的要求。

使用ImageIcon al = new ImageIcon(getClass().getResource("Walmart.jpeg")); 的{​​{1}}属性,并将selecteditem绑定到编辑屏幕/文本框。我在这里绑定了SelectedItem的建议。

查看-

ComboBox

View.cs-

SelectedTestItem.Name

答案 1 :(得分:0)

在此示例中,您甚至不需要INotifyPropertyChanged。我不确定您要实现的目标,但是此代码将实现我从您的帖子中学到的东西。

<Window x:Class="RaisePropertyChangedExample.BindingExample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Correct View" Width="150" Height="80">
   <StackPanel Orientation="Vertical">
      <ComboBox ItemsSource="{Binding Items}"
                x:Name="ItemViews"
                HorizontalAlignment="Stretch" VerticalAlignment="Center" DisplayMemberPath="Name"/>
      <TextBox DataContext="{Binding SelectedItem, ElementName=ItemViews}" Text="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
               HorizontalAlignment="Stretch" VerticalAlignment="Center"/>
   </StackPanel>
</Window>

和支持代码

using System.Windows;
using System.Collections.Generic;
using System.Collections.ObjectModel;

namespace RaisePropertyChangedExample
{
   public partial class BindingExample : Window
   {
      public BindingExample()
      {
         InitializeComponent();
         DataContext = new BindingExampleViewModel();
      }
   }

   public class BindingExampleViewModel
   {
      public ObservableCollection<TestItemViewModel> Items { get; set; }
         = new ObservableCollection<TestItemViewModel>(new List<TestItemViewModel>
         {
            new TestItemViewModel {Name = "Test1"},
            new TestItemViewModel {Name = "Test2"}
         });
   }

   public class TestItemViewModel
   {
      public string Name { get; set; }
   }
}

除非所选index中的Item有一定的需求,否则没有真正的理由反对将每个项目简单地公开为TestItemViewModel视图模型并将其他控件直接绑定到所选项目本身。但是,如果将其他控件绑定到TestItemViewModel的成员上,那么在该视图模型上实现INotifyPropertyChanged仍然不一定。

下面的示例与现有的ViewModel连线时仍将显示正确的信息:

<Window x:Class="RaisePropertyChangedExample.BindingExample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Correct View" Width="150" Height="100">
   <StackPanel Orientation="Vertical">
      <ComboBox ItemsSource="{Binding Items}"
                x:Name="Combo"
                HorizontalAlignment="Stretch" VerticalAlignment="Center" DisplayMemberPath="Name"/>
      <Grid DataContext="{Binding SelectedItem, ElementName=Combo}">
         <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
         </Grid.RowDefinitions>
         <TextBox Text="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                  HorizontalAlignment="Stretch" VerticalAlignment="Center"/>
         <Label Grid.Row="1" HorizontalAlignment="Stretch" Height="20" Content="{Binding Name}" />
      </Grid>
   </StackPanel>
</Window>

通常

  

每次击键后进行更新都会降低性能,并且会剥夺用户通常在提交新值之前退格并修复键入错误的机会see MS reference

但是,仅当更新源进行其他处理时,这才是问题。如果您担心所涉及的处理量,可以通过简单地省略“ UpdateSourceTrigger”声明来切换到默认行为LostFocus