动态在运行时向按钮控件上下文添加按钮

时间:2014-12-10 03:54:41

标签: c# .net wpf mvvm mvvm-light

我正处于MVVM环境中,并且我正在尝试向我的标签项添加内容。我的标签项是动态生成的,并且工作正常。为了简化这一点,我有一个字典,存储一个字符串作为键(标签项标题)和一个列表(当前按钮(我知道休息mvvm,我想摆脱打破mvvm模式))。我希望将我的按钮放在相应网格行/列中的项目上下文中。我已经查看过数据模板(如何将我的字典键映射到我的标签项标题),但不确定如何从列表中提取按钮对象。绑定到值将返回列表属性,而不是按钮属性。

我的第一个问题是如何在运行时将按钮放在列表中存储的选项卡控件上下文中。 我的第二个问题是如何确定它应该进入哪个网格行/列。我想使它成为真正的(呃)MVVM并使用数据模板触发器但是现在我将最小宽度/高度设置为存储网格行/列应该包含在。

这是我到目前为止所得到的:

<TabControl Margin="10,10,10,26" Grid.Column="0" ItemsSource="{Binding FUGU}">
        <TabControl.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Key}" />
            </DataTemplate>
        </TabControl.ItemTemplate>

        <TabControl.ContentTemplate>
            <DataTemplate>

            </DataTemplate>
        </TabControl.ContentTemplate>
...
</TabControl>

C#视图模型

public Dictionary<string, List<Button>> FUGU{ get; set; }
//inside constructor
foreach(var item in Items)
        {
            if (!Categories.Contains(item.Category))
            {
                Categories.Add(item.Category);
                List<Button> buttons = new List<Button>();
                int row = 0;
                int col = 0;
                foreach (var i in Items.FindAll(x => x.Category == item.Category))
                {
                    Button btn = new Button() { Content = i.Name, Tag = i.SKU, MinWidth=col, MinHeight=row };
                    buttons.Add(btn);
                    if(row==10)
                    {
                        row = 0;
                        col += 1;
                    }
                }
                FUGU.Add(item.Category, buttons);
            }

        }

编辑: 所以我做了一些更改并创建了一个对象并找到了ItemsControl类。这是我更新的代码:

<TabControl Margin="10,10,10,26" Grid.Column="0" ItemsSource="{Binding FUGU}" Background="#FFE5E5E5">
        <TabControl.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Key}" />
            </DataTemplate>
        </TabControl.ItemTemplate>

        <TabControl.ContentTemplate>
            <DataTemplate>


                <ItemsControl ItemsSource="{Binding Value}" >
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>

                            <Grid x:Name="grid">
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="*" />
                                    <ColumnDefinition Width="*" />
                                    <ColumnDefinition Width="*" />
                                    <ColumnDefinition Width="*" />
                                </Grid.ColumnDefinitions>

                                <Grid.RowDefinitions>
                                    <RowDefinition />
                                    <RowDefinition Height="0*" />
                                    <RowDefinition Height="0*" />
                                    <RowDefinition Height="0*" />
                                    <RowDefinition Height="0*" />
                                    <RowDefinition Height="0*" />
                                    <RowDefinition Height="0*" />
                                    <RowDefinition Height="0*" />
                                    <RowDefinition Height="0*" />
                                    <RowDefinition Height="0*" />
                                </Grid.RowDefinitions>
                                <Button Content="{Binding content}" Tag="{Binding tag}" Grid.Row="{Binding gridRow}" Grid.Column="{Binding gridCol}" Margin="5" FontSize="31"/>

                            </Grid>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>


            </DataTemplate>
        </TabControl.ContentTemplate>
    </TabControl>

C#视图模型

foreach(var item in Items)
        {
            if (!Categories.Contains(item.Category))
            {
                Categories.Add(item.Category);


                List<POSButtonInfo> btnInfoLst = new List<POSButtonInfo>();
                int row = 0;
                int col = 0;
                foreach (var i in Items.FindAll(x => x.Category == item.Category))
                {
                    btnInfoLst.Add(new POSButtonInfo { content = i.Name, tag = i.SKU, gridCol = col, gridRow = row });


                    if(row==9)
                    {
                        row = 0;
                        col += 1;
                    }
                    else
                        row+=1;
                }
                FUGU.Add(item.Category, btnInfoLst);
            }

        }

我的按钮中的绑定来自我的自定义对象。这些绑定工作正常但是,我得到一些意想不到的行为,例如在我看来,按钮不尊重网格,我的意思是我有10个行定义并创建了12个测试对象放入我的视图。正如您在代码中看到的那样,当命中9时(第10个元素),它应该转到下一列并从0开始。相反,它转到下一列,但不会重置第0行。此外,按钮对象不占据整列,在设计视图中查看时,只显示网格的第一行,而不是整个网格的普通视图。我是数据模板的新手,所以我确定我做错了什么。任何指导都将不胜感激。

1 个答案:

答案 0 :(得分:0)

我会做的是以下内容。在我的mainviewmodel中,我将使用我的tabitemviewmodels

创建一个列表
public List<ITabItemViewmodel> MyTabContent {get;private set}

然后我会用我希望在此选项卡中显示的viewmodels填充此列表,例如。

 MyTabContent.Add(new NameVm());
 MyTabContent.Add(new AdressVm());
 MyTabContent.Add(new OtherVm());

tabviewmodel看起来像这样

 public class NameVm : ITabItemViewmodel
 {
    public string HeaderText {get;set;}

    public ICommand MyCommand {get;set;}

    //other properties and stuff
 }

如果我有这么好的tabitemviewmodel,我可以简单地使用DataTemplates让wpf渲染我的视图

 <TabControl ItemsSource="{Binding MyTabContent}">
    <TabControl.ItemTemplate>
        <!-- this is the header template-->
        <DataTemplate>
            <TextBlock Text="{Binding HeaderText}" />
        </DataTemplate>
    </TabControl.ItemTemplate>
    <TabControl.ContentTemplate>
        <ContentPresenter Content="{Binding}"/>
    </TabControl.ContentTemplate>
</TabControl>

在资源中的任何位置,您当然应该为“TabItemViews”

定义DataTemplates
<DateTemplate DataType="{x:Type NameVm}">
 <view:MyViewForNameVm/>
<DataTemplate>

示例视图

 <UserControl x:class="view:MyViewForNameVm">
   <!-- here are all my Controls with bindings for my NameVm-->
   <Button Command="{Binding MyCommand}"/>
 </UserControl>