Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/283.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将自定义用户控件的StackPanel绑定到自定义类的ObservableCollection_C#_Wpf_Binding_Observablecollection_Stackpanel - Fatal编程技术网

C# 将自定义用户控件的StackPanel绑定到自定义类的ObservableCollection

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

我有一个名为NEXTBESTATIONS的ObservableCollection“”NEXTBESTATIONS,其中NEXTBESTATIONS是:

[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
}