C# 在可重用用户控件中绑定转换器参数
我正在尝试创建一个可重用的用户控件(用于数据输入),其中有两个文本框,它们通过C# 在可重用用户控件中绑定转换器参数,c#,wpf,binding,ivalueconverter,C#,Wpf,Binding,Ivalueconverter,我正在尝试创建一个可重用的用户控件(用于数据输入),其中有两个文本框,它们通过IValueConvertor链接到每个文本框 下面的XAML是原始的普通代码。这就是我试图在用户控件中重现的内容 <WrapPanel> <TextBlock Text="Length of Fence"/> <TextBox Name="Metric" Width="50" Text="{Binding Path=LengthFence, Mode=TwoWay}"/&
IValueConvertor
链接到每个文本框
下面的XAML是原始的普通代码。这就是我试图在用户控件中重现的内容
<WrapPanel>
<TextBlock Text="Length of Fence"/>
<TextBox Name="Metric" Width="50" Text="{Binding Path=LengthFence, Mode=TwoWay}"/>
<TextBlock Text="Meters"/>
<TextBox Text="{Binding ElementName=Metric, Path=Text, Converter={StaticResource MetersToInches}, StringFormat=N8}"/>
<TextBlock Text="Inches"/>
</WrapPanel>
这就是这个XAML的样子:
现在,我制作了一个可重用的UserControl
,它有三个用于标签字符串的依赖属性Label
,Value
用于在ViewModel中绑定属性,以及Units
——一个用于显示输入单位的字符串属性
<UserControl ...
x:Name="parent">
<StackPanel DataContext="{Binding ElementName=parent}">
<TextBlock Text="{Binding Path=Label}"/>
<TextBox Text="{Binding Path=Value}"/>
<TextBlock Text="{Binding Path=Units}"/>
</StackPanel>
但是,此可重用控件只能处理输入的第一个文本框。我不知道如何绑定第二个文本框中的IValueConvertor
。我需要这样做,因为我想绑定其他转换器,如米到英尺,千克到磅,等等
我已经读到,ConvertorParameter
无法绑定,因为它不是依赖属性,我不确定是否可以使用多重绑定,主要是因为我不知道如何正确使用它
如果您能告诉我如何执行此操作,或将我引导到StackOverflow上的相应链接或解决此问题的其他位置,我将非常感激。或者如果有更好的方法
非常感谢 不确定如何将多个转换器绑定到一个控件中。如果我没有错的话,您希望构建一个控件,当用户输入特定值时,您需要以不同的单位显示它。如果是这种情况,您可以创建一个转换器,转换器参数为“m”、“cm”、“inch”等,并在此基础上返回结果。在本例中,您将有4,5个控件,每个控件都有相同的转换器绑定,但转换器值不同。如果不清楚,您需要进一步的指导,请告知
多值绑定
要回答您的第6点,请参阅下面的示例多绑定转换器及其在xaml中的实现。我已经构建了一个简单的RolesFilter,它将从xaml获取不同的输入作为对象[],因为我已经知道需要什么样的数据,所以我正在转换器中转换它们
public class RolesFilter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
try
{
FlipperObservableCollection<Role> _roles = (FlipperObservableCollection<Role>)values[0]; //Input
Department _dept_param = values[1] as Department;
bool _filter = (bool)values[2];
string _id = "NA";
if (values.Count() == 4 && values[3] is string) _id = (string)values[3] ?? "NA";
//If we need a filter, then without department, it should return empty results
if (!_filter) return _roles; //If no filter is required, then don't worry, go ahead with input values.
if (_dept_param == null) return new FlipperObservableCollection<Role>(); //If department is null, then
List<Role> _filtered_list = _roles.ToList().Where(p => p.department.id == _dept_param.id && p.id != _id)?.ToList() ?? new List<Role>();
return new FlipperObservableCollection<Role>(_filtered_list);
}
catch (Exception)
{
throw;
}
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
公共类角色过滤器:IMultiValueConverter
{
公共对象转换(对象[]值,类型targetType,对象参数,CultureInfo区域性)
{
尝试
{
FlipperObservableCollection _roles=(FlipperObservableCollection)值[0];//输入
部门_dept_param=作为部门的值[1];
bool _filter=(bool)值[2];
字符串_id=“NA”;
如果(values.Count()==4&&values[3]为字符串)_id=(字符串)值[3]??“NA”;
//如果我们需要一个过滤器,那么没有部门,它应该返回空结果
如果(!\u filter)返回_roles;//如果不需要过滤器,那么不用担心,继续输入值。
如果(_dept_param==null)返回新的FlipperObservableCollection();//如果department为null,则
列表(过滤)列表=(角色)列表().其中(p=>p.department.id==(部门)参数id&&p.id!=(id))?.ToList()?新建列表();
返回新的FlipperObservableCollection(\u筛选的\u列表);
}
捕获(例外)
{
投掷;
}
}
公共对象[]转换回(对象值,类型[]目标类型,对象参数,CultureInfo区域性)
{
抛出新的NotImplementedException();
}
}
我在xaml中使用多值转换器,如下所示。在这里,我根据另一个组合框和复选框过滤组合框的itemsource。这只是一个示例,在您的示例中,您可以创建一个具有不同单位值的组合框。根据用户选择,您可以使用转换器并将值返回到文本框
<ComboBox Height="30" SelectedItem="{Binding reports_to, NotifyOnTargetUpdated=True, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}">
<ComboBox.ItemsSource>
<MultiBinding Converter="{StaticResource roles_filter}">
<Binding Source="{StaticResource SingletonData__}" Path="roles" NotifyOnSourceUpdated="True" UpdateSourceTrigger="PropertyChanged"/>
<Binding Path="department" NotifyOnSourceUpdated="True" UpdateSourceTrigger="PropertyChanged"/>
<Binding ElementName="cbx_filter" Path="IsChecked"/>
<Binding Path="id" NotifyOnSourceUpdated="True" UpdateSourceTrigger="PropertyChanged"/>
</MultiBinding>
</ComboBox.ItemsSource>
<ComboBox.ItemTemplate>
<DataTemplate>
<WrapPanel>
<TextBlock Text="{Binding department.name}"/>
<TextBlock Text=" - "/>
<TextBlock Text="{Binding name}"/>
</WrapPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
首先,不要将文本框
彼此绑定(如问题开头的原始代码),而是将每个文本框
绑定到相同的支持属性,在用户控件
中,该属性是值
至于如何实现多个绑定,您可能不需要多绑定
我们必须首先选择一个“标准”度量单位-这将是实际存储在属性和任何数据库或文件中的单位。我假设这个标准单位是米(m)。IValueConverter
可用于在米和其他距离单位之间进行转换,并使用ConverterParameter
指定要转换为/从哪个其他单位进行转换
这里有一个很好的例子让你开始
public enum DistanceUnit { Meter, Foot, Inch, }
public class DistanceUnitConverter : IValueConverter
{
private static Dictionary<DistanceUnit, double> conversions = new Dictionary<DistanceUnit, double>
{
{ DistanceUnit.Meter, 1 },
{ DistanceUnit.Foot, 3.28084 },
{ DistanceUnit.Inch, 39.37008 }
};
//Converts a meter into another unit
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return conversions[(DistanceUnit)parameter] * (double)value;
}
//Converts some unit into a meter
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null) { return 0; }
double v;
var s = value as string;
if (s == null)
{
v = (double)value;
}
else
{
if (s == string.Empty) { return 0; }
v = double.Parse(s);
}
if (v == 0) { return 0; }
return v / conversions[((DistanceUnit)parameter)];
}
}
距离单位
枚举
和内部转换
字典可以扩展为更多度量单位。或者,您可以使用已经包含所有这些内容的第三方库,例如。而不是将转换器保存在mainwindow.xaml代码中,而是将它们保存在单独的.cs文件中。您的第6点是正确的,您不能绑定到转换器参数,多重绑定就是答案。再次感谢。我已经把他们转移到了一个单独的班级。嗨,基思,谢谢你快速而详细的回复。这太棒了!每天我都在学习新的东西,谢谢你教我一个新的技巧。Th
public enum DistanceUnit { Meter, Foot, Inch, }
public class DistanceUnitConverter : IValueConverter
{
private static Dictionary<DistanceUnit, double> conversions = new Dictionary<DistanceUnit, double>
{
{ DistanceUnit.Meter, 1 },
{ DistanceUnit.Foot, 3.28084 },
{ DistanceUnit.Inch, 39.37008 }
};
//Converts a meter into another unit
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return conversions[(DistanceUnit)parameter] * (double)value;
}
//Converts some unit into a meter
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null) { return 0; }
double v;
var s = value as string;
if (s == null)
{
v = (double)value;
}
else
{
if (s == string.Empty) { return 0; }
v = double.Parse(s);
}
if (v == 0) { return 0; }
return v / conversions[((DistanceUnit)parameter)];
}
}
<StackPanel>
<StackPanel.Resources>
<local:DistanceUnitConverter x:Key="DistCon"/>
</StackPanel.Resources>
<StackPanel Orientation="Horizontal">
<TextBox Text="{Binding Distance, Converter={StaticResource DistCon}, ConverterParameter={x:Static local:DistanceUnit.Meter}}" MinWidth="20"/>
<TextBlock>m</TextBlock>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBox Text="{Binding Distance, Converter={StaticResource DistCon}, ConverterParameter={x:Static local:DistanceUnit.Foot}}" MinWidth="20"/>
<TextBlock>ft</TextBlock>
</StackPanel>
</StackPanel>