我目前正在为Windows 10构建一个WinRT应用程序,我正面临一个我似乎无法找到答案的问题。
在我的主页面中,我有一个绑定到ViewModel中的ObservableCollection的地图标记列表。对于这些标记中的每一个,我需要根据我的ViewModel的另一个属性(让我们称之为PropertySelector)的值显示一个可以是我的MapMarker类的Property1或Property2的文本。
我找到的最佳解决方案是在MapMarker类中创建一个包含Property1和Property2的结构,将其绑定到标记的文本字段,并使用Converter选择要显示的那个。
由于您无法将属性绑定到ConverterParameter,因此我在Converter中实现了DependencyProperty,以使其可以访问PropertySelector。 DP工作正常,转换器中的属性更新,但标记永远不会更新。我知道这是因为我没有触发任何实际告诉标记更新的事件,但我没有通过添加 PropertyChanged(" MarkerList&)来实现它。 #34;)到PropertySelector setter或者当我用 GetBinding(Text).UpdateSource()之类的东西更改属性时尝试以编程方式刷新绑定,顺便说一下与WPF有不同的实现。
我这样做了吗?我该怎么做才能强制绑定刷新?
以下是我的相关代码:
MainPage.xaml中
<Page.Resources>
<local:PropertySelectorConverter x:Key="propertySelectorConverter"
PropertySelector="{Binding PropertySelector}" />
</Page.Resources>
...
<Maps:MapControl>
<Maps:MapItemsControl ItemsSource="{Binding MarkerList}">
<Maps:MapItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Properties, Converter={StaticResource propertySelectorConverter}}" />
</DataTemplate>
</Maps:MapItemsControl.ItemTemplate>
</Maps:MapItemsControl>
</Maps:MapControl>
<Button Text="Switch Data" Click="SwitchButton_Click" />
MainPage.xaml.cs中
public void SwitchButton_Click(object sender, EventArgs e)
{
viewModel.PropertySelector= !viewModel.PropertySelector
}
ViewModel.cs
class ViewModel : INotifyPropertyChanged
{
private ObservableCollection<Marker> markerList = new ObservableCollection<Marker>();
public ObservableCollection<Marker> MarkerList
{
get { return markerList; }
set { markerList = value; OnPropertyChanged("MarkerList"); }
}
private bool propertySelector = false;
public bool PropertySelector
{
get { return propertySelector; }
set { propertySelector = value; OnPropertyChanged("PropertySelector"); }
}
}
Marker.cs
public class Marker
{
public Tuple<double, double> Properties { get; set; } = Tuple.Create(10, 7);
}
Converter.cs
public class PropertySelectorConverter : DependencyObject, IValueConverter
{
public bool PropertySelector
{
get { return (bool)GetValue(PropertySelectorProperty); }
set { SetValue(PropertySelectorProperty, value); }
}
public static readonly DependencyProperty PropertySelectorProperty =
DependencyProperty.Register("PropertySelector", typeof(bool), typeof(PropertySelectorConverter), new PropertyMetadata(null, CurrentItemChangedCallback));
private static void CurrentItemChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args)
{
}
public object Convert(object value, Type targetType, object parameter, string language)
{
var properties = (Tuple<double, double>)value;
return PropertySelector ? properties.Item1 : properties.Item2;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
感谢您的时间。
答案 0 :(得分:0)
缺乏明确说明您问题的a good, minimal, complete code example,即使不是不可能提供具体建议也很困难。但是有一些普遍的想法要分享......
首先,根据我的经验,ConverterParameter
对于提供给转换器的静态(即编译时)信息更有用。例如。当您编写了一个通用转换器,它需要某个给定绑定的特定数据,但在编译时该数据值是已知的。
在您的方案中,您实际上有多个转换器的输入值在运行时变化。对于这种情况,恕我直言,使用MultiBinding
更合适。这允许您提供两个或更多绑定源,如果其中任何一个源发生更改,WPF将重新计算绑定值。不幸的是,这是一个WPF功能,并且与许多非常有用的WPF功能一样,已从Windows Store / Winrt API中省略。
但是,您可以构建一个简单的中间视图模型类来完成相同的操作。例如:
class MultiBindingViewModel : DependencyObject
{
public static readonly DependencyProperty PropertiesProperty = DependencyProperty.Register(
"Properties", typeof(Tuple<double, double>), typeof(MultiBindingViewModel), new PropertyMetadata(null, OnPropertyChanged);
public static readonly DependencyProperty PropertySelectorProperty = DependencyProperty.Register(
"PropertySelector", typeof(bool), typeof(MultiBindingViewModel), new PropertyMetadata(null, OnPropertyChanged);
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
"Value", typeof(double), typeof(MultiBindingViewModel), null);
public Tuple<double, double> Properties
{
get { return (Tuple<double, double>)GetValue(PropertiesProperty); }
set { SetValue(PropertiesProperty, value); }
}
public bool PropertySelector
{
get { return (bool)GetValue(PropertySelectorProperty); }
set { SetValue(PropertySelectorProperty, value); }
}
public double Value
{
get { return (double)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
MultiBindingViewModel model = (MultiBindingViewModel)d;
model.Value = model.PropertySelector ? model.Properties.Item1 : model.Properties.Item2;
}
}
然后在您的XAML中使用它,例如:
<TextBlock>
<TextBlock.Text>
<Binding Path="Value">
<Binding.Source>
<local:MultiBindingViewModel Properties="{Binding Properties}"
PropertySelector="{Binding PropertySelector}/>
</Binding.Source>
</Binding>
</TextBlock.Text>
</TextBlock>
警告:缺少一个完整的代码示例,上面只是浏览器编写的代码。可能存在语法错误,或者我甚至可能遗漏了一些关键的Windows Store所需代码。当然,确切的绑定源,路径和XML命名空间可能需要一些调整,因为我无法确定您是如何设置数据上下文等的。
但希望上面清楚地说明了你可以在项目中使用它的基本方法。
为了完整性,以下是使用MultiBinding
的WPF方法:
MultiBinding
总是有一个转换器,实现IMultiValueConverter
。该接口的Convert()
方法与IValueConverter
的方法类似,不同之处在于,只有object value
参数允许转换单个输入值,它具有object[] values
参数
根据您提供的代码,我希望您的转换器看起来像这样:
public class PropertySelectorConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, string language)
{
var properties = (Tuple<double, double>)values[0];
bool propertySelector = (bool)values[1];
return propertySelector ? properties.Item1 : properties.Item2;
}
public object ConvertBack(object[] values, Type targetType, object parameter, string language)
{
throw new NotSupportedException();
}
}
然后在你的XAML中,你会做这样的事情:
<TextBlock>
<TextBlock.Text>
<MultiBinding Converter="{StaticResource propertySelectorConverter}">
<Binding Source="." Path="Properties"/>
<Binding Source="." Path="PropertySelector"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>