我想实现一个支持多设备同时更新固件的应用。如下图
插入多少个设备就显示多少个进度度。每个进度条上显示对应的串口及进度。
最终实现演示如下:
public MainWindow()
{
InitializeComponent();
List<DownloadProgress> test = new List<DownloadProgress>();
test.Add(new DownloadProgress() { Name = "COM1", Color = "#bf00ee" });
test.Add(new DownloadProgress() { Name = "COM2", Color = "#1122ee" });
test.Add(new DownloadProgress() { Name = "COM3", Color = "#005566" });
test.Add(new DownloadProgress() { Name = "COM4", Color = "#778899" });
test.Add(new DownloadProgress() { Name = "COM5", Color = "#bf00ee" });
test.Add(new DownloadProgress() { Name = "COM6", Color = "#1122ee" });
test.Add(new DownloadProgress() { Name = "COM7", Color = "#005566" });
test.Add(new DownloadProgress() { Name = "COM8", Color = "#778899" });
myListBox.ItemsSource = test;
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
for (int i = 0; i < myListBox.Items.Count; i++)
{
// Object o = myListBox.Items.GetItemAt(i);
ListBoxItem myListBoxItem = (ListBoxItem)(myListBox.ItemContainerGenerator.ContainerFromItem(myListBox.Items.GetItemAt(i)));
// Getting the currently selected ListBoxItem
// Note that the ListBox must have
// IsSynchronizedWithCurrentItem set to True for this to work
// ListBoxItem myListBoxItem = (ListBoxItem)(myListBox.ItemContainerGenerator.ContainerFromItem(myListBox.Items.CurrentItem));
// Getting the ContentPresenter of myListBoxItem
ContentPresenter myContentPresenter = FindVisualChild<ContentPresenter>(myListBoxItem);
// Finding textBlock from the DataTemplate that is set on that ContentPresenter
DataTemplate myDataTemplate = myContentPresenter.ContentTemplate;
//TextBlock myTextBlock = (TextBlock)myDataTemplate.FindName("textBlock", myContentPresenter);
// Do something to the DataTemplate-generated TextBlock
//MessageBox.Show("The text of the TextBlock of the selected list item: " + myTextBlock.Text);
ProgressBar myProgress = (ProgressBar)myDataTemplate.FindName("Progress", myContentPresenter);
myProgress.Value = i+10;
}
}
界面
<Window x:Class="WpfM20UpdateFW.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfM20UpdateFW"
mc:Ignorable="d"
Title="M20 Update Firmware V1.0 " Height="600" Width="800" Closed="Window_Closed">
<Window.Resources>
<RoutedUICommand x:Key="download" Text="download"/>
</Window.Resources>
<Window.InputBindings>
<KeyBinding Gesture="Alt+D" Key="D" Command="{StaticResource download}"></KeyBinding>
</Window.InputBindings>
<Window.CommandBindings>
<CommandBinding Command="{StaticResource download}" CanExecute="Button_Click"></CommandBinding>
</Window.CommandBindings>
<Grid>
<Grid ShowGridLines="false" MinWidth="20" FocusManager.FocusedElement="{Binding ElementName=download}">
<Grid.RowDefinitions>
<RowDefinition Height="0.05*"></RowDefinition>
<RowDefinition Height="0.55*"></RowDefinition>
<RowDefinition Height="0.3*"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.6*"></ColumnDefinition>
<ColumnDefinition Width="0.2*"></ColumnDefinition>
<ColumnDefinition Width="0.2*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBox x:Name="Path" Grid.Row="0" Grid.Column="0" IsReadOnly="True"/>
<Button Grid.Row="0" Grid.Column="1" Click="Button_Click_1">Open...</Button>
<Button x:Name="download" Grid.Row="0" Grid.Column="2" Click="Button_Click" >Download</Button>
<ListBox Grid.Row="1" Grid.ColumnSpan="3" x:Name="myListBox" HorizontalContentAlignment="Stretch">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<ProgressBar x:Name="Progress"/>
<TextBlock x:Name="textBlock" FontSize="22" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock.Text >
<MultiBinding StringFormat="{}{0} {1}%">
<Binding Path="Name"/>
<Binding Path="Value" ElementName="Progress"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<TextBox x:Name="logText" Grid.Row="2" Grid.ColumnSpan="3" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" AcceptsReturn="True" IsReadOnly="True" />
</Grid>
</Grid>
</Window>
现在已经实现了动态显示多个进度条。还需要实现:
1.进度前显示串口号,比如COM1等。
2.每个进度条能控制显示进度。
<Window x:Class="WpfM20UpdateFW.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfM20UpdateFW"
mc:Ignorable="d"
Title="M20 Update Firmware V1.0 " Height="600" Width="800" Closed="Window_Closed">
<Window.Resources>
<RoutedUICommand x:Key="download" Text="download"/>
</Window.Resources>
<Window.InputBindings>
<KeyBinding Gesture="Alt+D" Key="D" Command="{StaticResource download}"></KeyBinding>
</Window.InputBindings>
<Window.CommandBindings>
<CommandBinding Command="{StaticResource download}" CanExecute="Button_Click"></CommandBinding>
</Window.CommandBindings>
<Grid>
<Grid ShowGridLines="false" MinWidth="20" FocusManager.FocusedElement="{Binding ElementName=download}">
<Grid.RowDefinitions>
<RowDefinition Height="0.05*"></RowDefinition>
<RowDefinition Height="0.55*"></RowDefinition>
<RowDefinition Height="0.3*"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.6*"></ColumnDefinition>
<ColumnDefinition Width="0.2*"></ColumnDefinition>
<ColumnDefinition Width="0.2*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBox x:Name="Path" Grid.Row="0" Grid.Column="0" IsReadOnly="True"/>
<Button Grid.Row="0" Grid.Column="1" Click="Button_Click_1">Open...</Button>
<Button x:Name="download" Grid.Row="0" Grid.Column="2" Click="Button_Click" >Download</Button>
<ListBox Grid.Row="1" Grid.ColumnSpan="3" x:Name="list" HorizontalContentAlignment="Stretch">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<ProgressBar x:Name="Progress"/>
<Label Content="{Binding Path=Value,ElementName=Progress}" ContentStringFormat=" {0}%" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="22"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<TextBox x:Name="logText" Grid.Row="2" Grid.ColumnSpan="3" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" AcceptsReturn="True" IsReadOnly="True" />
</Grid>
</Grid>
</Window>
如何解决1:使用MultiBinding 解决了。
<Label Content="{Binding Path=Value,ElementName=Progress}" ContentStringFormat="{} {0}%" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="22"/>
以下贴出MSDN官方的解决方法
ControlTemplate
https://docs.microsoft.com/zh-cn/dotnet/framework/wpf/controls/how-to-find-controltemplate-generated-elements
DataTemplate
https://docs.microsoft.com/zh-cn/dotnet/framework/wpf/data/how-to-find-datatemplate-generated-elements
以上要注意常出现null的问题
ControlTemplate里这种用法只能获取直接关联的子元素,如果是像ItemBox,ItemView等等里的item元素是获取不到的,还有,因为UI需要加载窗体,需要一个时间,所以要注意顺序,不能在构造函数中获取ControlTemplate,那样会显示null,可以再窗体load事件以及控件的事件中使用
DataTemplate要注意以上方法是通过遍历item得到的,也就是说如果你的ItemBox,ItemView等等还没加载数据源,即没有item时不能使用,会报null