开发者

Combobox binded to ViewModel property does not updates when the property changes

I have a ComboBox populated with the available items of an enum 开发者_StackOverflow中文版thru ItemSource and binded to the ViewModel property WorkingMode:

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

If I change the selected item of the ComboBox manually the ViewModel property changes its value as expected but if I change the property value of the ViewModel the ComboBox does not change what it's shown to the user.

The ViewModel implements INotifyPropertyChanged and the event is raised when the value change. Even more, activating WPF logging with:

diag:PresentationTraceSources.TraceLevel=High

I get the following information when the ViewModel property changed it's value to All (one of the enum values):

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'

So looks like the ComboBox received the new value, but nothing changed on it (it remains showing the last value, other than All).

Any help will be great! Thanks.

My code:

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
}
}


pls post your VM code. i created a testproject and all works fine.

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
}

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
}


you need to set UpdateSourceTrigger=PropertyChanged

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

hope this helps

this will give you a detailed explanation UpdateSourceTrigger – DataBinding

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜