问题
I'm trying to do simple binding using a converter to display count of elements inside observable collection that satisfy given enum, let's say A B C D.
The code below works when I test it with my other project, but on the most basic project binding doesn't get updated. The exact same code works inside other project (really strange).
How I'm doing the binding
<Label Content="{Binding Source={x:Static viewmodels:TestViewModel.Instance}, Path=TestModels, Converter={StaticResource TestConverter}, Mode=OneWay}"></Label>
Converter
class TestConverter : IValueConverter
{
public object Convert(
object value,
Type targetType,
object parameter,
CultureInfo culture)
{
if (value == null)
return 0;
var v = (ObservableCollection<TestModel>)value;
return $"{v.Count} / {v.AsParallel().Count(x => x.TestEnum == TestEnum.A)} / {v.AsParallel().Count(x => x.TestEnum == TestEnum.B)} / {v.AsParallel().Count(x => x.TestEnum == TestEnum.C)} / {v.AsParallel().Count(x => x.TestEnum == TestEnum.D)}";
}
public object ConvertBack(
object value,
Type targetType,
object parameter,
CultureInfo culture)
{
throw new NotImplementedException();
}
}
Model
public enum TestEnum { A, B, C, D }
public class TestModel:INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private TestEnum _testEnum;
public TestModel()
{
TestEnum = (TestEnum)(TestViewModel.Instance.rnd.Next(0,3));
}
public TestEnum TestEnum
{
get
{
return _testEnum;
}
set
{
_testEnum = value;
PropertyChanged?.Invoke(this,new PropertyChangedEventArgs(null));
}
}
}
ViewModel
public class TestViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private static readonly TestViewModel _instance = new TestViewModel();
public Random rnd = new Random();
public static TestViewModel Instance
{
get
{
return _instance;
}
}
private ObservableCollection<TestModel> _testModels;
private TestViewModel()
{
_testModels = new ObservableCollection<TestModel>();
}
public ObservableCollection<TestModel> TestModels
{
get { return _testModels;}
set
{
_testModels = value;
PropertyChanged?.Invoke(this,new PropertyChangedEventArgs(null));
}
}
}
Simple test case that I'm trying to get to work
for (var i = 0; i != 100; i++)
{
TestViewModel.Instance.TestModels.Add(new TestModel());
}
回答1:
You're binding to the TestModels
collection, so the converter is only going to be invoked when that property changes. Your loop changes the elements within the collection but it doesn't change the value of TestModels
itself. If you want this to work then you basically have two options:
1) Use an attached behaviour and make it subscribe to the INotifyCollectionChanged CollectionChanged
property when the TestModels
binding is first made. It will then need some way of providing the result back to the Label, that can be achieved with a separate attached property.
2) Do all this in your view model, which is really where it should be being done anyway. Any time you find yourself doing anything but the most basic, application-independent tasks in your converters it's usually a sign that your view model layer isn't doing its job properly.
来源:https://stackoverflow.com/questions/36585758/c-sharp-wpf-mvvm-binding-not-updating