使用 material 设计 WPF 动态添加控件

Add control dynamically using material design WPF

我是 WPF 新手。我想使用 Material 设计的桌面应用程序之一。我添加了 MaterialDesign nuget 包并成功实施。 在这种情况下,我需要在单击按钮时添加按钮或卡片。那些是完全动态的。 我可以从 C# 动态添加 material 设计控件吗? 帮我举个例子。

提前致谢

我相信您可能正在使用 Material Design In XAML. Make sure to check out the demo project。包含常见控件用法的所有答案。

选项一。

您通常会使用 "ItemsControl" 将对象动态加载到视图中。项目控件链接到后端视图模型中的项目源。源应该是 ObservableCollection 类型。当您向此源提供项目时,ItemsControl 将根据它提供的模板进行更新和插入。

下面是一个基本的简短示例。

xaml

        <ItemsControl  ItemsSource="{Binding ItemsToLoad}" Grid.IsSharedSizeScope="True" Margin="12 0 12 0">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                       <Button>Hi</Button>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
        </ItemsControl>

我假设您对绑定有很好的理解,所以我不会发布所有后端代码。

选项二

以编程方式

看到你提到你想以编程方式进行,你也可以这样做:

第 1 步:创建网格并设置供您使用的布局。

<Grid x:Name="grid_Main">

    <Grid.ColumnsDefinition>
        <ColumnDefinition/>
        <ColumnDefinition/>
    </Grid.ColumnsDefinition>

    <Grid.RowDefinition>
        <RowDefinition/>
        <RowDefinition/>
     </Grid.RowDefinition>

 </Grid>

第 2 步:代码隐藏。

  private void AddControlToGrid()
  {
        Button button = new Button();
        grid_Main.Children.Add(button );
        Grid.SetRow(button , 1); // 1 is row index
        Grid.SetColumn(button , 0);// 0 is column index
  }

只是 material 设计用法的注释。您需要先引用该库,然后才能在您的视图中使用它。

像这样:

将此添加到您的应用程序资源中。

    <Application x:Class="demo_app.App"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:local="clr-namespace:demo_app">
    <Application.Resources>
       <ResourceDictionary>
           <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Light.xaml" />
                <ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml" />
                <ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Primary/MaterialDesignColor.DeepPurple.xaml" />
                <ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Accent/MaterialDesignColor.Lime.xaml" />
            </ResourceDictionary.MergedDictionaries>
       </ResourceDictionary>
     </Application.Resources>
 </Application>

将此引用添加到您需要使用 material 设计控件的任何视图。

xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"

然后您可以像这样使用 material 设计控件。

<materialDesign:Card Width="200">
            <Grid>
               <!--Content-->
            </Grid>
</materialDesign:Card>

我参考了以下 link 的 material 设计解决方案。 How to generate WPF controls automatically based on XML file? 我不知道这种方式在 material 设计中是否有效,但我成功地获得了卡片控制的结果。

    StackPanel stackPanel = new StackPanel();
    MaterialDesignThemes.Wpf.Card card = new MaterialDesignThemes.Wpf.Card();
    StringBuilder sb = new StringBuilder();

    //Create card
sb.Append(@"<materialDesign:Card xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' xmlns:materialDesign='http://materialdesigninxaml.net/winfx/xaml/themes' Background='#03a9f4' Foreground = '{DynamicResource PrimaryHueDarkForegroundBrush}' Padding = '0' Width = '200'> ");
sb.Append(@"<Grid><Grid.RowDefinitions><RowDefinition Height='Auto' /><RowDefinition Height = 'Auto' /><RowDefinition Height = 'Auto' /></Grid.RowDefinitions> ");
sb.Append(@"<TextBlock Grid.Row='0' Margin = '16 16 16 4' Style = '{StaticResource MaterialDesignHeadlineTextBlock}'> Call Jennifer </TextBlock><Separator Grid.Row = '1' Style = '{StaticResource MaterialDesignLightSeparator}' /><TextBlock Grid.Row = '2' Margin = '16 0 16 8' VerticalAlignment = 'Center' HorizontalAlignment = 'Left' Style = '{StaticResource MaterialDesignBody2TextBlock}'> March 19, 2016 </TextBlock>");
sb.Append(@"</Grid></materialDesign:Card>");

    card = (MaterialDesignThemes.Wpf.Card)XamlReader.Parse(sb.ToString());
    // Add created button to previously created container.
    stackPanel.Children.Add(card);
    this.Content = stackPanel;

如果我们仔细观察, xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' xmlns:materialDesign='http://materialdesigninxaml.net/winfx/xaml/themes' 准备新的动态控件时,以上属性无能为力。

我从上面的代码得到的结果Dynamic Material design control

您可以简单地这样做:

Card card = new Card();
StackPanel stackPanel = new StackPanel { Orientation = Orientation.Vertical };
stackPanel.Children.Add(new Label { Content = "Test"});
card.Content = stackPanel;

我是这样做的。下面的 Xaml 改编自 Material Design In XAML nuget package GitHub 示例。

"smtx:XamlDisplay" 来自 "ShowMeTheXaml",也用于 GitHub 演示 (https://github.com/MaterialDesignInXAML/MaterialDesignInXamlToolkit/blob/master/MainDemo.Wpf/Progress.xaml)

   <smtx:XamlDisplay x:Name="prgDisplay" Key="progress" Grid.Row="2" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="12" Visibility="Hidden">
          <materialDesign:Card  UniformCornerRadius="99" Padding="4" Opacity="0.95" Background="{StaticResource BrushPrimaryLight}">
              <ProgressBar Style="{StaticResource MaterialDesignCircularProgressBar}" 
                             Value="50" IsIndeterminate="True"                                      
                             Foreground="{StaticResource BrushPrimaryDark}" 
                             Height="100" Width="100"/>
           </materialDesign:Card>
    </smtx:XamlDisplay>

如果您使用的是 MVVM,则在后面的代码或其他地方。

 private void ToggleProgressBarVisibility()
  {
     if (prgDisplay.Visibility == Visibility.Visible)
        prgDisplay.Visibility = Visibility.Hidden;
     else
        prgDisplay.Visibility = Visibility.Visible;
  }