C# 将自定义用户控件的StackPanel绑定到自定义类的ObservableCollection
我有一个名为NEXTBESTATIONS的ObservableCollection“”NEXTBESTATIONS,其中NEXTBESTATIONS是:C# 将自定义用户控件的StackPanel绑定到自定义类的ObservableCollection,c#,wpf,binding,observablecollection,stackpanel,C#,Wpf,Binding,Observablecollection,Stackpanel,我有一个名为NEXTBESTATIONS的ObservableCollection“”NEXTBESTATIONS,其中NEXTBESTATIONS是: [TypeConverter(typeof(NextBestActionTypeConverter))] public class NextBestAction : IDisposable { public bool isDismissable, dismissed, completed; public NextBestActi
[TypeConverter(typeof(NextBestActionTypeConverter))]
public class NextBestAction : IDisposable
{
public bool isDismissable, dismissed, completed;
public NextBestActionType type;
public string title, description;
public void Dispose()
{
this.Dispose();
}
public NextBestAction()
{
}
public NextBestAction(string title, string description)
{
this.title = title;
this.description = description;
}
public static NextBestAction Parse(Card card)
{
if (card == null)
{
return new NextBestAction();
}
return new NextBestAction(card.Title.Text, card.Description.Text);
}
}
我还有自己的用户控件,名为Card,其中Card是:
public partial class Card : UserControl
{
public Card()
{
InitializeComponent();
this.DataContext = this;
}
public Card(string title, string description)
{
InitializeComponent();
this.DataContext = this;
this.Title.Text = title;
this.Description.Text = description;
}
public static Card Parse(NextBestAction nextBestAction)
{
if (nextBestAction == null)
{
return new Card();
}
return new Card(nextBestAction.title, nextBestAction.description);
}
}
使用富灵XAML:
<UserControl x:Class="AdvancedTeller.Card"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:AdvancedTeller"
mc:Ignorable="d"
d:DesignWidth="300" Background="White" BorderBrush="#FF333333" VerticalContentAlignment="Top" Width="400">
<Grid Margin="10" VerticalAlignment="Top">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Name="Title" Grid.Column="1" Grid.Row="0" FontSize="18.667" Margin="3"/>
<TextBlock Name="Description" Grid.Column="1" Grid.Row="1" VerticalAlignment="Top" TextWrapping="Wrap" Margin="3"/>
</Grid>
我试图将NextBestActions绑定到StackPanel,并强制在UI中将NextBestActions表示为卡片
到目前为止,我知道我至少需要这个
<StackPanel Grid.Column="1" Grid.Row="1" Grid.RowSpan="2" Margin="50" >
<ItemsControl Name="NextBestActionItems" ItemsSource="{Binding NextBestActions}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<AdvancedTeller:Card />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
及
及
我可以看到您的代码中有一些潜在的问题点 首先,看起来您没有完整的属性,使用
get;设置代码>访问器方法,为下一个设置
对象中的标题
和说明
定义
如果我没记错的话,WPF的绑定系统需要具有get/set访问器的完整属性,并且不会绑定到没有这些属性的字段
所以
应该成为
public string Title { get; set; }
public string Description { get; set; }
另一个潜在的问题可能是,您没有在卡
用户控件中绑定Title/Description文本框的.Text属性
因此,假设您没有使用基于.Name
属性(如Caliburn Micro)自动创建绑定的框架,则此代码
<TextBlock Name="Title" ... />
<TextBlock Name="Description" ... />
(顺便说一句,我不知道你在用这个类型转换器做什么:)它通常用于将一种类型转换为另一种类型,例如,当你键入类似于
的内容时,将字符串“Red”
更改为SolidColorBrush
,并将.Color
设置为红色。我看不出它在您当前的代码中有什么用处,建议您完全删除它,除非您出于某些特定原因需要它。)我注意到您的卡中的标题和说明文本框
UserControl没有任何文本绑定。这是故意的(比如使用Caiburn Micro)还是疏忽?可能是疏忽。我想我可以在卡片的构造函数中设置标题和描述的文本,该构造函数将由TypeConverter调用。但是,永远不会调用TypeConverter。如果我删除XAML中的ItemTemplate,则会调用TypeConverter,但目标类型为“string”。我希望ItemsControl调用目标类型为“Card”的TypeConverter。我明白你的意思,我知道你为什么这么说,我做了更改,它工作得非常好!但我仍然不完全理解为什么这些更改会被编译。如果卡片的构造函数甚至不需要接受来自TypeConverter的标题和描述,那么卡片如何处理它们呢?@MichaelDeLuca WPF应用程序有两层:UI和数据(DataContext)。绑定用于将数据从数据层拉入UI层。默认情况下,数据层从父控件继承,除非您通过设置.DataContext
属性(与代码中的属性类似)另行指定。我经常从WPF初学者那里看到这个错误,所以我写了一篇博文来链接到so-。请随意查看以了解更多详细信息:)@MichaelDeLuca至于TypeConverter,我一开始甚至不知道它是什么,除非您正在使用WPF进行更高级的操作,否则通常不会使用它。当您编写类似于
的东西时,实际处理的更像var s=new StackPanel();s、 背景=“红色”
,但是这里的问题是.Background
是画笔
属性,而的“Red”
是字符串。因此,TypeConverter被用来自动将字符串转换为笔刷对象。我的意思是,如果你看一下我的编辑,其中包含了修改后的代码段,它为什么能工作呢?我是否不需要定义一个解析器来设置卡片的标题和描述,以及基于底层类的任何其他参数?例如,假设NextBestAction和NextBestProduct都有标题和说明,但我希望其中一个由红色背景卡表示,另一个由绿色背景卡表示,设置此类参数是否不需要解析器或特殊卡构造函数?@MichaelDeLuca在设置ItemsSource时,它告诉WPF在集合中循环,并为每个项创建一个
,将.Content
属性设置为对象。因此WPF尝试绘制对象,在本例中,该对象是NextBestAction
。这可能就是为什么在您不指定数据模板时使用TypeConverter的原因-它试图将NextBestAction
转换为字符串,以便将其呈现给UI。修复UserControl中的绑定是另一个问题-阅读.DataContext
更多信息后,如果您还有问题,请告诉我:)
public partial class Card : UserControl
{
public Card()
{
InitializeComponent();
}
}
<UserControl x:Class="AdvancedTeller.Card"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:AdvancedTeller"
mc:Ignorable="d"
d:DesignWidth="300" Background="White" BorderBrush="#FF333333" VerticalContentAlignment="Top" Width="400">
<Grid Margin="10" VerticalAlignment="Top">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Name="Title" Grid.Column="1" Grid.Row="0" FontSize="18.667" Margin="3" Text="{Binding Title}"/>
<TextBlock Name="Description" Grid.Column="1" Grid.Row="1" VerticalAlignment="Top" TextWrapping="Wrap" Margin="3" Text="{Binding Description}"/>
</Grid>
public string title, description;
public string Title { get; set; }
public string Description { get; set; }
<TextBlock Name="Title" ... />
<TextBlock Name="Description" ... />
<TextBlock Name="Title" Text="{Binding Title}" ... />
<TextBlock Name="Description" Text="{Binding Description}" ... />
public Card()
{
InitializeComponent();
this.DataContext = this; // Bad!
}
public Card(string title, string description)
{
InitializeComponent();
this.DataContext = this; // Bad!
this.Title.Text = title; // Should be replaced with bindings as above
this.Description.Text = description; // Should be replaced with bindings as above
}