在与Binding一起使用的转换器中有一些我无法理解的东西。 : - (
我用Mvvm-Light创建了一个简单的例子......
这里是完整的解决方案:https://testbindingwithconverter.codeplex.com/SourceControl/latest
这里有一张图片:http://i.stack.imgur.com/wUf89.png
以及摘要源代码:
CarsView
<Rectangle Grid.Row="0"
Opacity="{Binding SelectedCar, Converter={StaticResource IntToOpacityConverter}}"
Fill="#FFD1E22A" />
<ListBox Grid.Row="1"
ItemsSource="{Binding Cars}"
SelectedItem="{Binding SelectedCar, Mode=TwoWay}" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Company}" />
<TextBlock Text="{Binding Name}" />
<TextBlock Text="{Binding Year}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
CarsViewModel
public class CarsViewModel : ViewModelBase
{
private ObservableCollection<Car> cars;
private Car selectedCar;
public CarsViewModel()
{
if (IsInDesignMode)
{
}
else
{
// INIT
this.cars = new ObservableCollection<Car>();
this.selectedCar = null;
// FAKE DATA
for (int i = 1; i <= 10; i++)
{
Car newCar = new Car { Id = i, Company = "Company_" + i, Name = "Name_" + i, Year = "200" + i };
Cars.Add(newCar);
}
}
}
public ObservableCollection<Car> Cars
{
get
{
return cars;
}
set
{
if (cars != value)
{
cars = value;
RaisePropertyChanged(() => Cars);
}
}
}
public Car SelectedCar
{
get
{
return selectedCar;
}
set
{
if (value != selectedCar)
{
selectedCar = value;
RaisePropertyChanged(() => SelectedCar);
}
}
}
}
转换器
public class IntToOpacityConverter : System.Windows.Data.IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
double opacity = 1;
Car c = value as Car;
if (c != null)
{
if (c.Id == 5)
{
opacity = 0.3;
}
}
System.Diagnostics.Debug.WriteLine("[IntToOpacityConverter] \t" + "Rectangle Opacity: " + opacity);
return opacity;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
// One-Way conversion!
return null;
}
在CarsView中,当我点击ListBox的第5项时,属性Opacity of Rectangle设置为值0.3,否则设置为值1.
现在,当我回到HomeView然后再回到CarsView时,如果我点击项目之间转换器被称为2次! 再次,如果我回到HomeView并返回到CarsView,转换器被称为3次!等等...
为什么?
答案 0 :(得分:1)
嘿Vincenzo Petronio,
我不会为每次导航创建一个新的CarsViewModel(),因为它不会将颜色保存在Rectangle上,而是在你离开时想要取消绑定DataContent。
在 CarsView.xaml / CarsView.xaml.cs 上创建一个卸载的事件:
<phone:PhoneApplicationPage Unloaded="PhoneApplicationPage_Unloaded">
private void PhoneApplicationPage_Unloaded(object sender, RoutedEventArgs e)
{
this.DataContext = null;
}
然后你需要检查你的Car Set函数的空值,这样它就不会把你的选择改为null。
public Car SelectedCar
{
get
{
System.Diagnostics.Debug.WriteLine("[CARSVIEWMMODEL] \t" + "GET SelectedCar");
return selectedCar;
}
set
{
if (value != selectedCar && value != null)
{
selectedCar = value;
System.Diagnostics.Debug.WriteLine("[CARSVIEWMMODEL] \t" + "SET SelectedCar");
RaisePropertyChanged(() => SelectedCar);
}
}
}
如果您应用更改,您将看到它将按您希望的方式运行,另外,当您导航回Cars页面时,它将保存该Rectangle的颜色。
答案 1 :(得分:0)
从您描述的内容中可以清楚地看到&#34; CarsView&#34;实例正在泄漏 - 当您在应用程序中导航回来时,它们不会被丢弃。这导致它们像幻影一样徘徊,仍然绑定到视图模型,因此无论什么时候触发转换调用&#34; SelectedCar&#34;得到更新。
我想知道你的视图模型定位器的设置是否有点错误(我不会使用这种模式,所以我不知道)。理论上,XAML运行时使用弱事件侦听器进行绑定,即使视图模型仍然保持绑定,也允许处理视图。这可能不是这种情况,因为绑定应用于页面中的StaticResource ...
我会尝试这个:使用瞬态范围进行视图模型实例化。这可以防止IOC容器保持对视图模型的引用,从而使其成为GC&#39; d:
public CarsViewModel CarsVM
{
get
{
return new CarsViewModel();
}
}
我意识到这会打破你的IOC模式,但如果这解决了问题,那么至少你会知道最近的原因。
修改强>
要尝试的另一件事:将定位器放在视图模型的资源中,而不是放在应用程序资源中。这可能会鼓励视图被处理,因为静态资源引用将由页面拥有。
<phone:PhoneApplicationPage.Resources>
<vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" />
</phone:PhoneApplicationPage.Resources>
<Grid x:Name="LayoutRoot" DataContext="{Binding Source={StaticResource Locator},Path=CarsVM}">