绑定一个已绑定的 属性 但具有规范化值
Binding an already bound property but with a normalised value
我的ProgressBar
XAML:
<Window ...>
<ProgressBar Value="{Binding Path=Progress}"/>
</Window>
代码隐藏:
internal int Progress { get; set; }
此进度变量是 1 的倍数,因此值为 1、2、3,依此类推...
现在我决定对 TaskBarItemInfo
的 ProgressValue
使用相同的 Progress
属性。但是,我发现它只接受 0.0 到 1.0 的范围(即 normalised 值)。有没有一种方法可以绑定相同的 Progress
属性,同时指定某种转换,例如除以数字以使其标准化?
xaml代码:
<Window.Resources>
<local:DataConverter x:Key="dataConverter " />
</Window.Resources>
<ProgressBar Value={Binding Path=Progress, Converter={StaticResource dataConverter }}/>
转换器代码
public class DataConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
// read the input from value and cast it
// return your object;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return null;
}
}
有多种选择。您可以公开一个单独的(可能是计算的)double
属性,每次 Progress
属性 更改时都会更新,例如通过在其 setter 中为计算出的 属性.
引发一个 PropertyChanged
(INotifyPropertyChanged
) 事件
另一种选择是创建自定义值或 multi-value 转换器。如果您的 int
进度值有硬编码或预定义的范围,您可以像这样创建一个值转换器。
public class AbsoluteToRelativeProgressConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (!(value is int progress) ||
!(parameter is string maximumText) ||
!int.TryParse(maximumText, out var maximum))
return Binding.DoNothing;
if (maximum < progress)
throw new ArgumentException("Progress must not exceed maximum.");
return progress / (double)maximum;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return new NotImplementedException();
}
}
此转换器获取作为 value
传入的绑定进度值。检查此值是否真的是 int
。作为参数,您可以传递最大值。它作为 string
传递以简化 XAML 中的语法(分配 int
是冗长的)。转换器 returns 在 [0.0, 1.0] 范围内的相对进度为 double
。如前所述,如果最大值是硬编码的,您可以删除参数用法并将 maximum
替换为值。
接下来,在 Window.Resources
或范围内的任何其他资源字典中创建转换器实例。
<Window.Resources>
<local:AbsoluteToRelativeProgressConverter x:Key="AbsoluteToRelativeProgressConverter"/>
</Window.Resources>
然后使用转换器将TaskBarItemInfo
中的Progress
绑定到ProgressValue
。 ConverterParameter
用于传递最大值,这里以 100
为例。请注意,您需要将 ProgressState
设置为例如Normal
、Error
或Paused
,否则不显示进度条。
<Window.TaskbarItemInfo>
<TaskbarItemInfo ProgressState="Normal"
ProgressValue="{Binding Progress, Converter={StaticResource AbsoluteToRelativeProgressConverter}, ConverterParameter=100}"/>
</Window.TaskbarItemInfo>
<Window.Resources>
<local:AbsoluteToRelativeProgressMultiConverter x:Key="AbsoluteToRelativeProgressMultiConverter"/>
</Window.Resources>
如果你也想绑定最大值,你需要像这样创建一个IMultiValueConverter
。
public class AbsoluteToRelativeProgressMultiConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values is null ||
values.Length != 2 ||
!(values[0] is int progress) ||
!(values[1] is int maximum))
return Binding.DoNothing;
if (maximum < progress)
throw new ArgumentException("Progress must not exceed maximum.");
return progress / (double)maximum;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
它的工作原理相同,但允许绑定多个值。在这里,进度是转换器的第一个值,最大值是第二个。您可以轻松地扩展此转换器,也可以绑定一个最小值。
在 XAML 中,您也创建了一个实例,但这次您使用 MultiBinding
。
<Window.Resources>
<local:AbsoluteToRelativeProgressMultiConverter x:Key="AbsoluteToRelativeProgressMultiConverter"/>
</Window.Resources>
<Window.TaskbarItemInfo>
<TaskbarItemInfo ProgressState="Normal">
<TaskbarItemInfo.ProgressValue>
<MultiBinding Converter="{StaticResource AbsoluteToRelativeProgressMultiConverter}">
<Binding Path="Progress"/>
<Binding Path="Maximum"/>
</MultiBinding>
</TaskbarItemInfo.ProgressValue>
</TaskbarItemInfo>
</Window.TaskbarItemInfo>
注意,如果你想让 ProgressState
依赖于 Progress
属性,比如设置 Normal
如果进度是 >= 0
和 <= maximum
,你猜怎么着,你可以使用创建一个转换器......或者当然是一个单独的 属性。
我的ProgressBar
XAML:
<Window ...>
<ProgressBar Value="{Binding Path=Progress}"/>
</Window>
代码隐藏:
internal int Progress { get; set; }
此进度变量是 1 的倍数,因此值为 1、2、3,依此类推...
现在我决定对 TaskBarItemInfo
的 ProgressValue
使用相同的 Progress
属性。但是,我发现它只接受 0.0 到 1.0 的范围(即 normalised 值)。有没有一种方法可以绑定相同的 Progress
属性,同时指定某种转换,例如除以数字以使其标准化?
xaml代码:
<Window.Resources>
<local:DataConverter x:Key="dataConverter " />
</Window.Resources>
<ProgressBar Value={Binding Path=Progress, Converter={StaticResource dataConverter }}/>
转换器代码
public class DataConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
// read the input from value and cast it
// return your object;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return null;
}
}
有多种选择。您可以公开一个单独的(可能是计算的)double
属性,每次 Progress
属性 更改时都会更新,例如通过在其 setter 中为计算出的 属性.
PropertyChanged
(INotifyPropertyChanged
) 事件
另一种选择是创建自定义值或 multi-value 转换器。如果您的 int
进度值有硬编码或预定义的范围,您可以像这样创建一个值转换器。
public class AbsoluteToRelativeProgressConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (!(value is int progress) ||
!(parameter is string maximumText) ||
!int.TryParse(maximumText, out var maximum))
return Binding.DoNothing;
if (maximum < progress)
throw new ArgumentException("Progress must not exceed maximum.");
return progress / (double)maximum;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return new NotImplementedException();
}
}
此转换器获取作为 value
传入的绑定进度值。检查此值是否真的是 int
。作为参数,您可以传递最大值。它作为 string
传递以简化 XAML 中的语法(分配 int
是冗长的)。转换器 returns 在 [0.0, 1.0] 范围内的相对进度为 double
。如前所述,如果最大值是硬编码的,您可以删除参数用法并将 maximum
替换为值。
接下来,在 Window.Resources
或范围内的任何其他资源字典中创建转换器实例。
<Window.Resources>
<local:AbsoluteToRelativeProgressConverter x:Key="AbsoluteToRelativeProgressConverter"/>
</Window.Resources>
然后使用转换器将TaskBarItemInfo
中的Progress
绑定到ProgressValue
。 ConverterParameter
用于传递最大值,这里以 100
为例。请注意,您需要将 ProgressState
设置为例如Normal
、Error
或Paused
,否则不显示进度条。
<Window.TaskbarItemInfo>
<TaskbarItemInfo ProgressState="Normal"
ProgressValue="{Binding Progress, Converter={StaticResource AbsoluteToRelativeProgressConverter}, ConverterParameter=100}"/>
</Window.TaskbarItemInfo>
<Window.Resources>
<local:AbsoluteToRelativeProgressMultiConverter x:Key="AbsoluteToRelativeProgressMultiConverter"/>
</Window.Resources>
如果你也想绑定最大值,你需要像这样创建一个IMultiValueConverter
。
public class AbsoluteToRelativeProgressMultiConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values is null ||
values.Length != 2 ||
!(values[0] is int progress) ||
!(values[1] is int maximum))
return Binding.DoNothing;
if (maximum < progress)
throw new ArgumentException("Progress must not exceed maximum.");
return progress / (double)maximum;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
它的工作原理相同,但允许绑定多个值。在这里,进度是转换器的第一个值,最大值是第二个。您可以轻松地扩展此转换器,也可以绑定一个最小值。
在 XAML 中,您也创建了一个实例,但这次您使用 MultiBinding
。
<Window.Resources>
<local:AbsoluteToRelativeProgressMultiConverter x:Key="AbsoluteToRelativeProgressMultiConverter"/>
</Window.Resources>
<Window.TaskbarItemInfo>
<TaskbarItemInfo ProgressState="Normal">
<TaskbarItemInfo.ProgressValue>
<MultiBinding Converter="{StaticResource AbsoluteToRelativeProgressMultiConverter}">
<Binding Path="Progress"/>
<Binding Path="Maximum"/>
</MultiBinding>
</TaskbarItemInfo.ProgressValue>
</TaskbarItemInfo>
</Window.TaskbarItemInfo>
注意,如果你想让 ProgressState
依赖于 Progress
属性,比如设置 Normal
如果进度是 >= 0
和 <= maximum
,你猜怎么着,你可以使用创建一个转换器......或者当然是一个单独的 属性。