UWP中如何在ConverterParameter中传递元素(替代WPF的x:Reference)
在UWP中替代x:Reference传递元素到ConverterParameter的方案
嘿,这个问题我做UWP项目时也踩过坑!确实UWP不支持在ConverterParameter里用x:Reference,不过有几个实用的替代方案,完全能实现你要的效果,给你详细说说:
方案1:使用MultiBinding(最推荐)
UWP支持MultiBinding,我们可以把原本的绑定值和要传递的DataGrid元素一起作为转换器的输入,直接绕开ConverterParameter的限制。
XAML代码示例:
<DataTemplate> <TextBlock Foreground="Blue" Background="Yellow" FontSize="15"> <TextBlock.Text> <MultiBinding Converter="{StaticResource CaptionSummaryRowConverter}"> <!-- 第一个绑定:原本的数据源对象 --> <Binding /> <!-- 第二个绑定:要传递的DataGrid元素,通过ElementName定位 --> <Binding ElementName="dataGrid" /> </MultiBinding> </TextBlock.Text> </TextBlock> </DataTemplate>
对应的转换器修改:
你需要把原来的IValueConverter改成IMultiValueConverter,这样就能在Convert方法里拿到两个参数:
public class CaptionSummaryRowConverter : IMultiValueConverter { public object Convert(object[] values, Type targetType, object parameter, string language) { // values[0] 是原本的绑定对象 // values[1] 就是你要的DataGrid实例 var originalData = values[0]; var dataGrid = values[1] as DataGrid; // 这里写你的转换逻辑 return GenerateSummaryText(originalData, dataGrid); } public object[] ConvertBack(object value, Type[] targetTypes, object parameter, string language) { throw new NotImplementedException(); } private object GenerateSummaryText(object originalData, DataGrid dataGrid) { // 你的业务逻辑实现 } }
方案2:自定义附加属性
如果不想用MultiBinding,可以通过自定义附加属性来传递DataGrid元素,再在转换器里通过这个属性获取目标元素。
第一步:定义附加属性
在项目里创建一个静态类,定义附加属性:
public static class DataGridHelper { public static readonly DependencyProperty TargetDataGridProperty = DependencyProperty.RegisterAttached( "TargetDataGrid", typeof(DataGrid), typeof(DataGridHelper), new PropertyMetadata(null)); public static void SetTargetDataGrid(DependencyObject element, DataGrid value) { element.SetValue(TargetDataGridProperty, value); } public static DataGrid GetTargetDataGrid(DependencyObject element) { return (DataGrid)element.GetValue(TargetDataGridProperty); } }
第二步:在XAML中使用
给TextBlock设置附加属性,并通过RelativeSource把自身作为转换器参数:
<DataTemplate> <TextBlock local:DataGridHelper.TargetDataGrid="{Binding ElementName=dataGrid}" Foreground="Blue" Background="Yellow" FontSize="15" Text="{Binding Converter={StaticResource CaptionSummaryRowConverter}, RelativeSource={RelativeSource Self}}" /> </DataTemplate>
第三步:修改转换器逻辑
在转换器里通过附加属性获取DataGrid:
public class CaptionSummaryRowConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, string language) { // parameter是TextBlock实例,通过附加属性拿到DataGrid var textBlock = parameter as TextBlock; var dataGrid = DataGridHelper.GetTargetDataGrid(textBlock); // value是原本的绑定对象,执行你的转换逻辑 return GenerateSummaryText(value, dataGrid); } public object ConvertBack(object value, Type targetType, object parameter, string language) { throw new NotImplementedException(); } private object GenerateSummaryText(object originalData, DataGrid dataGrid) { // 你的业务逻辑实现 } }
方案3:ViewModel中持有元素引用(不推荐,需谨慎)
如果你的项目用MVVM架构,也可以把DataGrid的引用放到ViewModel里,但要注意内存泄漏问题,必须用弱引用:
public class YourViewModel : INotifyPropertyChanged { private WeakReference<DataGrid> _dataGridRef; public WeakReference<DataGrid> DataGridRef { get => _dataGridRef; set { _dataGridRef = value; OnPropertyChanged(); } } // 页面加载时赋值:DataGridRef = new WeakReference<DataGrid>(dataGrid); }
然后在转换器里绑定这个弱引用属性,不过这个方法不如前两个优雅,只适合特殊场景。
内容的提问来源于stack exchange,提问作者Sam10
相关产品推荐
相关产品推荐

