关于 c#:Refresh 与绑定到其他属性的转换器的绑定
Refresh binding with converter bound to other property
我目前正在为 Windows 10 构建一个 WinRT 应用程序,但我遇到了一个我似乎无法找到答案的问题。
在我的主页中,我的 ViewModel 中有一个绑定到 ObservableCollection 的地图标记列表。对于这些标记中的每一个,我需要根据我的 ViewModel 的另一个属性(我们称之为 PropertySelector)的值,从我的 MapMarker 类中显示一个可以是 Property1 或 Property2 的文本。
我找到的最佳解决方案是在 MapMarker 类中创建一个同时包含 Property1 和 Property2 的结构,将其绑定到标记的文本字段并使用转换器选择要显示的一个。
由于您无法将属性绑定到 ConverterParameter,因此我在 Converter 中实现了 DependencyProperty 以使其能够访问 PropertySelector。 DP 工作正常,转换器中的属性得到更新,但标记永远不会更新。我知道这是因为我没有触发任何实际告诉标记更新的事件,但是我没有通过将 PropertyChanged("MarkerList") 添加到 PropertySelector 设置器或尝试以编程方式刷新绑定来实现它当我用 GetBinding(Text).UpdateSource() 之类的东西更改属性时,顺便说一下,这似乎与 WPF 有不同的实现。
我这样做对吗?我能做些什么来强制绑定刷新?
这是我的相关代码:
MainPage.xaml
|
<Page.Resources>
<local:PropertySelectorConverter x:Key="propertySelectorConverter" PropertySelector="{Binding PropertySelector}" /> </Page.Resources> ... <Maps:MapControl> |
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; |
Marker.cs
|
public class Marker
{ public Tuple<double, double> Properties { get; set; } = Tuple.Create(10, 7); } |
转换器.cs
|
public class PropertySelectorConverter : DependencyObject, IValueConverter
{ public bool PropertySelector { get { return (bool)GetValue(PropertySelectorProperty); } set { SetValue(PropertySelectorProperty, value); } } public static readonly DependencyProperty PropertySelectorProperty = private static void CurrentItemChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args) } public object Convert(object value, Type targetType, object parameter, string language) public object ConvertBack(object value, Type targetType, object parameter, string language) |
感谢您的宝贵时间。
缺少一个好的、最小的、完整的代码示例来清楚地说明您的问题,即使不是不可能,也很难提供具体的建议。但是有一些一般的想法要分享……
首先,根据我的经验,
在您的场景中,您实际上有多个在运行时变化的转换器输入值。对于这种情况,恕我直言,使用
但是,您可以构建一个简单的中间视图模型类来完成相同的任务。例如:
|
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 public bool PropertySelector public double Value private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 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 应用商店所需的关键代码。当然,确切的绑定源、路径和 XML 命名空间可能需要一些调整,因为我无法确定您是如何设置数据上下文等的。
但希望以上内容清楚地显示了您可以在项目中使用它的基本方法。
为了完整起见,以下是使用
根据您提供的代码,我希望您的转换器如下所示:
|
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) |
然后在你的 XAML 中,你会做这样的事情:
|
<TextBlock>
<TextBlock.Text> <MultiBinding Converter="{StaticResource propertySelectorConverter}"> <Binding Source="." Path="Properties"/> <Binding Source="." Path="PropertySelector"/> </MultiBinding> </TextBlock.Text> </TextBlock> |
相关讨论
- 我知道 MultiBinding 及其在 WinRT 中的缺失,但我认为我无法重新创建它。我会继续尝试实现这一点,它看起来很有希望。非常感谢您的宝贵时间 !
- 效果很好,但您需要将 MultiBindingViewModel 放在 DataTemplate 资源中,而不是直接放在 Text 绑定中。
- @JabX 您介意解释一下您对数据模板资源的含义吗? afaik 数据模板没有资源属性,如果直接在属性绑定中写入,它确实不起作用。
- 好的,它使用了数据模板的第一个孩子的资源。但是,现在当其中一个绑定更改时,它不会更新。
- @Stefan:感谢您纠正我的错字。至于您的具体问题,听起来您应该发布一个新问题,如果您仍然无法使代码正常工作。确保您包含一个良好的、最小的、完整的代码示例,可以可靠地重现问题。此外,请具体说明正在发生的事情(例如,"绑定更改"可能意味着绑定属性的值,或者实际用于绑定的不同属性)。
- @PeterDuniho 是的,我知道。我已经解决了。它不喜欢绑定到其他元素的属性(数据模板资源之外)。由于我需要的属性无论如何都是静态的,因此我在 ViewModel 类中对绑定进行了建模。