我有一个组合框,它绑定到MyObject类型的对象列表:
public class MyObject
{
public string Template { get; set; }
public string Parameter { get; set; }
}
字符串“Template”是一个应该与String.Format一起使用的字符串,即它可能包含应该用字符串“Parameter”替换的“{0}”。
我想在标签中显示结果,而不必在viewmodel中添加新字段。我正在寻找类似于此的XAML:
<ComboBox Name="cbMyObjects" ItemsSource="{Binding Path=MyObjects}"/>
<Label Name="lblDisplay2" Content="{Binding ElementName=cbMyObjects, Path=SelectedItem.Parameter}" ContentStringFormat="{Binding ElementName=cbMyObjects, Path=SelectedItem.Template}" />
即。如果列表中有一个对象,使得Template =“Weight:{0}”,参数=“3kg”,则标签应显示“Weight:3kg”
答案 0 :(得分:1)
我接受了Michael Coxon的回答并使用转换器制作了一个版本,以避免使用ToString()
基本上,您可以使用MultiBinding
和IMultiValueConverter
以相当通用的方式解决您的问题,string.Format()
基本上是<Window
x:Class="SandBox.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:SandBox"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:properties="clr-namespace:SandBox.Properties"
Title="{x:Static properties:Resources.TitleSandbox}"
mc:Ignorable="d">
<ComboBox
HorizontalAlignment="Center"
VerticalAlignment="Center"
ItemsSource="{Binding MyObjects}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock>
<TextBlock.Text>
<MultiBinding Converter="{local:TemplateConverter}">
<Binding Path="Template" />
<Binding Path="Parameter" />
<Binding Path="Double" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</Window>
public class MainWindowViewModel
{
public MainWindowViewModel()
{
}
public IEnumerable<MyObject> MyObjects
{
get
{
yield return new MyObject { Template = "The parameter value is {0} with double value of {1:F2}", Parameter = "asdF1", Double = 1.0 / 3.0 };
yield return new MyObject { Template = "The parameter value is {0} with double value of {1:F2}", Parameter = "asdF2", Double = 4.5 };
yield return new MyObject { Template = "The parameter value is {0} with double value of {1:F2}", Parameter = "asdF3", Double = 78 };
yield return new MyObject { Template = "The parameter value is {0} with double value of {1:F2}", Parameter = "asdF4", Double = Double.PositiveInfinity };
}
}
}
public class MyObject
{
public string Template { get; set; }
public string Parameter { get; set; }
public double Double { get; set; }
}
/// <summary>
/// Permit {local:TemplateConverter} markup
/// </summary>
public class TemplateConverterExtension : MarkupExtension
{
public override object ProvideValue(IServiceProvider serviceProvider)
=> new TemplateConverter();
}
public class TemplateConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values.Length >= 1 && values[0] is string template)
{
return string.Format(template, values.Skip(1).ToArray());
}
throw new ArgumentException("Give at least a template");
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
=> throw new NotImplementedException("Todo, eventually");
}
// Fill the contact list
procedure TForm1.FillContactList(Source: TAddressBookSource);
var
I: Integer;
Contacts: TAddressBookContacts;
begin
Contacts := TAddressBookContacts.Create;
try
AddressBook1.AllContacts(Source, Contacts);
ListViewContacts.BeginUpdate;
try
ListViewContacts.Items.Clear;
for I := 0 to Contacts.Count - 1 do
AddListViewItem(Contacts.Items[I]);
finally
ListViewContacts.EndUpdate;
end;
finally
Contacts.Free;
end;
end;
答案 1 :(得分:0)
为什么不覆盖ToString()
在MyObject
public override string ToString()
{
return string.Format(this.Template, this.Parameter);
}
然后,如果绑定到SelectedItem,则会在引擎盖下调用ToString()
方法。
答案 2 :(得分:0)
所以我不确定这是否是你要找的,但我设法使用我在评论中提出的ToString()
方法和MainWindow
类的属性来使用它。 ..以下所有代码......
看起来ToString()
使用值和您建议用于标签的模板填充组合框。
<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<StackPanel >
<ComboBox Name="cbMyObjects" ItemsSource="{Binding MyObjects, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MainWindow}}}"/>
<Label Name="lblDisplay2" Content="{Binding ElementName=cbMyObjects, Path=SelectedItem.Parameter}" ContentStringFormat="{Binding ElementName=cbMyObjects, Path=SelectedItem.Template}" />
</StackPanel>
</Grid>
</Window>
namespace WpfApp1
{
using System.Collections.Generic;
using System.Windows;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
public IEnumerable<MyObject> MyObjects
{
get
{
yield return new MyObject { Template = "The parameter value is {0}", Parameter = "asdF1" };
yield return new MyObject { Template = "The parameter value is {0}", Parameter = "asdF2" };
yield return new MyObject { Template = "The parameter value is {0}", Parameter = "asdF3" };
yield return new MyObject { Template = "The parameter value is {0}", Parameter = "asdF4" };
}
}
}
}
public class MyObject
{
public string Template { get; set; }
public string Parameter { get; set; }
public override string ToString() => string.Format(this.Template, this.Parameter);
}