绑定到ViewModel属性的Combobox在属性更改时不会更新

时间:2011-06-21 09:49:41

标签: wpf data-binding combobox binding

我有一个ComboBox填充了枚举项目源的枚举项,并绑定到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属性将其值更改为All(其中一个枚举值)时,我得到以下信息:

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>

View.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 个答案:

答案 0 :(得分:1)

发布您的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();
    }


}

枚举:

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

VM:

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
}

答案 1 :(得分:0)

您需要设置UpdateSourceTrigger=PropertyChanged

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

希望这会有所帮助

这将给你一个详细的解释 UpdateSourceTrigger – DataBinding