Поле со списком, привязанное к свойству ViewModel, не обновляется при изменении свойства - PullRequest
0 голосов
/ 21 июня 2011

У меня есть ComboBox, заполненный доступными элементами перечисления через ItemSource и связанный со свойством ViewModel WorkingMode:

<ComboBox ItemsSource="{Binding Source={StaticResource WorkingModeEnum}}" SelectedItem="{Binding Path=WorkingMode, Mode=TwoWay" />

Если я вручную изменю выбранный элемент ComboBox, свойство ViewModel изменит его значениекак и ожидалось, но если я изменю значение свойства ViewModel, ComboBox не изменит то, что показано пользователю.

ViewModel реализует INotifyPropertyChanged, и событие вызывается при изменении значения.Более того, активируя ведение журнала WPF с помощью:

diag:PresentationTraceSources.TraceLevel=High

Я получаю следующую информацию, когда свойство ViewModel изменило свое значение на Все (одно из значений перечисления):

System.Windows.Data Warning: 86 : BindingExpression (hash=50934842): Update - got raw value 'All'
System.Windows.Data Warning: 89 : BindingExpression (hash=50934842): Update - implicit converter produced 'All'
System.Windows.Data Warning: 90 : BindingExpression (hash=50934842): Update - using final value 'All'

Так выглядиткак ComboBox получил новое значение, но ничего не изменилось (он показывает последнее значение, кроме All).

Любая помощь будет отличной!Спасибо.

Мой код:

App.xaml:

 <Application x:Class="TestCombo.App"
 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 Startup="OnStartup">
 <Application.Resources>

 </Application.Resources>
 </Application>

View.xaml:

<Window x:Class="TestCombo.View"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:System="clr-namespace:System;assembly=mscorlib"
xmlns:TestCombo="clr-namespace:TestCombo"
Title="View" Height="300" Width="300">

<Window.Resources>
    <ObjectDataProvider x:Key="TestEnum" MethodName="GetNames" ObjectType="{x:Type System:Enum}">
        <ObjectDataProvider.MethodParameters>
            <x:Type TypeName="TestCombo:TestEnum"/>
        </ObjectDataProvider.MethodParameters>
    </ObjectDataProvider>
</Window.Resources>

<Grid>
    <StackPanel>
        <ComboBox ItemsSource="{Binding Source={StaticResource TestEnum}}" SelectedItem="{Binding Path=Test, Mode=TwoWay, PresentationTraceSources.TraceLevel=High}"/>
        <Button Height="23" Name="button1" VerticalAlignment="Bottom" Click="button1_Click">Button</Button>
        <TextBlock Grid.Row="2" Text="{Binding Test, Mode=OneWay}"/>
    </StackPanel>
</Grid>

Просмотреть.xaml.cs:

using System.Windows;

namespace TestCombo
{
public partial class View : Window
{
    public View()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        ((ViewModel) this.DataContext).Test = TestEnum.Three;
    }
}
}

ViewModel.cs:

using System.ComponentModel;

namespace TestCombo
{
public class ViewModel : INotifyPropertyChanged
{
    public Model Model { get; private set; }

    public event PropertyChangedEventHandler PropertyChanged;

    public ViewModel()
    {
        this.Model = new Model();
    }

    public TestEnum Test
    {
        get
        {
            return this.Model.Test;
        }
        set
        {
            if (this.Model.Test != value)
            {
                this.Model.Test = value;
                this.OnPropertyChanged("Test");
            }
        }

    }
    protected virtual void OnPropertyChanged(string name)
    {
        var handler = this.PropertyChanged;

        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }
}
}

Model.cs:

namespace TestCombo
{
public class Model
{
    public TestEnum Test { get; set; }
}

public enum TestEnum
{
    Zero = 0,
    One = 1,
    Two = 2,
    Three = 3,
    Four = 4
}
}

Ответы [ 2 ]

1 голос
/ 21 июня 2011

Пожалуйста, оставьте свой код VM.Я создал тестовый проект, и все отлично работает.

SampleCode:

<UserControl x:Class="WpfStackoverflow.ComboboxEnumSelectedValue"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:System="clr-namespace:System;assembly=mscorlib" 
         xmlns:local="clr-namespace:WpfStackoverflow" mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
    <ObjectDataProvider x:Key="WorkingModeEnum" MethodName="GetValues" ObjectType="{x:Type System:Enum}">
        <ObjectDataProvider.MethodParameters>
            <x:Type TypeName="local:WorkingMode"/>
        </ObjectDataProvider.MethodParameters>
    </ObjectDataProvider>
</UserControl.Resources>
<StackPanel>
    <Button Content="Test Set All" Click="Button_Click" />
    <ComboBox ItemsSource="{Binding Source={StaticResource WorkingModeEnum}}" SelectedItem="{Binding Path=SelectedWorkingMode, Mode=TwoWay}"/>
    <TextBlock Text="{Binding SelectedWorkingMode, Mode=OneWay}"/>
</StackPanel>

.cs

public partial class ComboboxEnumSelectedValue : UserControl
{
    private WorkingVM vm = new WorkingVM();
    public ComboboxEnumSelectedValue()
    {
        InitializeComponent();
        this.DataContext = vm;
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        vm.SetAllModeForTesting();
    }


}

Enum:

public enum WorkingMode
{
    Mode1,
    Mode2,
    Mode3,
    All
}

ВМ:

public class WorkingVM : INotifyPropertyChanged
{
    private WorkingMode _selectedmode;

    public void SetAllModeForTesting()
    {
        this.SelectedWorkingMode = WorkingMode.All;
    }

    public WorkingMode SelectedWorkingMode
    {
        get { return _selectedmode; }
        set { _selectedmode = value;
        this.OnPropertyChanged("SelectedWorkingMode");
        }
    }

    #region Implementation of INotifyPropertyChanged

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string propertyname)
    {
        var handler = PropertyChanged;

        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyname));
        }
    }

    #endregion
}
0 голосов
/ 21 июня 2011

нужно установить UpdateSourceTrigger=PropertyChanged

SelectedItem="{Binding WorkingMode, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"

надеюсь, это поможет

это даст вам подробное объяснение UpdateSourceTrigger - привязка данных

...