如何制作动态C#控件

时间:2015-11-03 09:26:26

标签: c# forms dynamic data-binding

我正在开发一个项目,需要一些关于绑定的帮助...

我有一份产品清单,可以属于配送中心。我想创建一个动态表单,即可以根据信息的可用性自行决定应该显示哪些内容。

基本上,该发行版目前有3种可以报告的产品,但这个数字是可变的。它现在应该显示3个条目,但是应该有更多(或更少)它应该能够处理它。

例如,我想将DistributionCenter的Name属性绑定到一种标题标签,不同的产品名称以及每个产品的数量应显示为两个标签(动态部分)。

我希望我有道理。这是模型代码,GUI尚未实现,因为我需要帮助那部分。

namespace Stock
{
    public partial class MainWindow : Window
    {
        public class Product
        {
            // accessors
            public string Code { get; set; }
            public string Name { get; set; }
            public int Quantity { get; set; }
            private int Threshold { get; set; }

            // constructor
            public Product(string code, string name, int quantity, int threshold)
            {
                this.Code = code;
                this.Name = name;
                this.Quantity = quantity;
                this.Threshold = threshold;
            }
        }
        public class DistributionCentre
        {
            // accessors
            public string Name { get; set; }
            public List<Product> p = new List<Product>();

            // constructor
            public DistributionCentre(string name, Product product)
            {
                this.p.Add(product);
            }
        }

        public class StockEngine
        {
            public StockEngine()
            {
                // register a few products
                Product p1 = new Product("1001", "Product1", 10, 5);
                Product p2 = new Product("1002", "Product2", 6, 5);
                Product p3 = new Product("1003", "Product3", 8, 5);

                // assign these products to a DC
                DistributionCentre ClinicA = new DistributionCentre("DC1", p1);
            }
        }

        public MainWindow()
        {            
            StockEngine control = new StockEngine();
            InitializeComponent();
        }
    }

编辑: 我还创建了以下控件,并希望将控件绑定到C#类的相关成员。对此的任何帮助都将不胜感激。

<UserControl x:Class="Stock.ReportingCard"
         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" 
         mc:Ignorable="d" 
         d:DesignHeight="37" d:DesignWidth="300">
<Grid Height="35">
    <Label Content="Product" Height="25" HorizontalAlignment="Left" Name="Product" VerticalAlignment="Top" Width="67" Margin="5,5,0,0" />
    <Label Content="Quantity" Height="30" HorizontalAlignment="Left" Margin="78,5,0,0" Name="Quantity" VerticalAlignment="Top" Width="59" />
    <Button Content="Plus" Height="24" HorizontalAlignment="Left" Margin="171,6,0,0" Name="PlusButton" VerticalAlignment="Top" Width="44" />
    <Button Content="Minus" Height="24" HorizontalAlignment="Left" Margin="233,6,0,0" Name="MinusButton" VerticalAlignment="Top" Width="44" />
</Grid>

1 个答案:

答案 0 :(得分:0)

你好@Harriet老实说我在提供的代码中看到了很多问题,但是我不打算解决大部分问题,因为它也有点主观,我觉得你的问题太广泛而且有些误导但是我会解决那些让我感兴趣的部分,并给你一些指导和示例如何修复这部分。

为简单起见,我不会使用您提供的整个结构,并注意到绑定按预期工作(例如,您在视图模型中更改了某些内容 - &gt;您的UI更新,反之亦然),您需要实现 INotifyPropertyChanged 或使用一些MVVM框架,如 MVVM Light Prism 等......这样做会为你做(有更多东西)< / p>

所以我们要解决的问题是对不同类型的产品进行不同的(动态)控制(不确定你是否考虑到了这一点,但这是我对动态控制的理解)

我们将使用我喜欢的两种方法中的一种来解决MSDN中的此类问题,稍微修改了以下示例版本:DataTemplateSelector

(我在这里使用过的另一个:WPF Based Dynamic DataTemplateSelector

public class ProductsDataTemplateSelector : DataTemplateSelector
{
    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        FrameworkElement element = container as FrameworkElement;

        if (element != null && item != null && item is Product)
        {
            Product productitem = item as Product;

            if (productitem.Code == "1001" || productitem.Code == "1003")
            {
                return element.FindResource("1001ProductTemplate") as DataTemplate;
            }
            else if (productitem.Code == "1002")
            {
                return element.FindResource("1002ProductTemplate") as DataTemplate;
            }
            else
            {
                return element.FindResource("UnknownProductTemplate") as DataTemplate;
            }
        }

        return null;
    }
}

这是用于说明3种不同类型的动态控件的XAML和包含我们在后面的代码中定义的所有产品的ListView

        

    <DataTemplate x:Key="1001ProductTemplate">
        <Grid Height="35" Background="Red">
            <Label Content="{Binding Path=Name}" Height="25" HorizontalAlignment="Left" Name="Product" VerticalAlignment="Top" Width="67" Margin="5,5,0,0" />
            <Label Content="{Binding Path=Quantity}" Height="30" HorizontalAlignment="Left" Margin="78,5,0,0" Name="Quantity" VerticalAlignment="Top" Width="59" />
            <Button Content="Plus" Height="24" HorizontalAlignment="Left" Margin="171,6,0,0" Name="PlusButton" VerticalAlignment="Top" Width="44" />
            <Button Content="Minus" Height="24" HorizontalAlignment="Left" Margin="233,6,0,0" Name="MinusButton" VerticalAlignment="Top" Width="44" />
        </Grid>
    </DataTemplate>

    <DataTemplate x:Key="1002ProductTemplate">
        <Grid Height="35" Background="Green">
            <Label Content="{Binding Path=Name}" Height="25" HorizontalAlignment="Left" Name="Product" VerticalAlignment="Top" Width="67" Margin="5,5,0,0" />
            <Label Content="{Binding Path=Quantity}" Height="30" HorizontalAlignment="Left" Margin="78,5,0,0" Name="Quantity" VerticalAlignment="Top" Width="59" />
            <Button Content="Minus" Height="24" HorizontalAlignment="Left" Margin="233,6,0,0" Name="MinusButton" VerticalAlignment="Top" Width="44" />
            <Button Content="Plus" Height="24" HorizontalAlignment="Left" Margin="171,6,0,0" Name="PlusButton" VerticalAlignment="Top" Width="44" />
        </Grid>
    </DataTemplate>

    <DataTemplate x:Key="UnknownProductTemplate">
        <Grid Height="35" Background="Blue">
            <Label Content="{Binding Path=Name}" Height="25" HorizontalAlignment="Left" Name="Product" VerticalAlignment="Top" Width="67" Margin="5,5,0,0" />
            <Label Content="{Binding Path=Quantity}" Height="30" HorizontalAlignment="Left" Margin="78,5,0,0" Name="Quantity" VerticalAlignment="Top" Width="59" />
        </Grid>
    </DataTemplate>

</Window.Resources>

<Grid>
    <ListView ItemTemplateSelector="{StaticResource ResourceKey=productDTSelector}"
              x:Name="ListView">

    </ListView>
</Grid>

我们将在后面的代码中使用一个简单的产品列表

public MainWindow()
{
    InitializeComponent();
    //StockEngine control = new StockEngine();

    var products = new List<Product>();

    Product p1 = new Product("1001", "Product1", 10, 5);
    Product p2 = new Product("1002", "Product2", 6, 5);
    Product p3 = new Product("1003", "Product3", 8, 5);
    Product p4 = new Product("999", "Some Prod", 8, 5);
    Product p5 = new Product("1002", "Product4", 10, 10);

    products.Add(p1);
    products.Add(p2);
    products.Add(p3);
    products.Add(p4);
    products.Add(p5);

    ListView.ItemsSource = products;
}

所以这些代码的作用是:拥有一个带有源的ListView - 您的产品,模板选择器负责为集合中的每个产品返回正确的模板(取决于它们的代码)。使用控件的不同结构或样式说明了不同的模板(我使用了您的示例控件,只是添加了一些简单的绑定到产品的属性)

如果有人发现这个答案偏离主题而没有帮助,请告诉我,我会把它放下。