WPF ListBox populated by another project dll and no block UI

//xaml
<Window x:Class="WpfApp9.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:WpfApp9"
        mc:Ignorable="d"
        WindowState="Maximized"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <ListBox x:Name="lbx"
                 ItemsSource="{Binding TimeGuidCollection,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
                 SelectedIndex="{Binding SelectedIdx,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
                 SelectedItem="{Binding SelectedStr,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
                    VirtualizingPanel.IsVirtualizing="True"
                    VirtualizingPanel.IsContainerVirtualizable="True"
                    VirtualizingPanel.CacheLength="1"
                    VirtualizingPanel.CacheLengthUnit="Item"
                    >
            <ListBox.ItemContainerStyle>
                <Style TargetType="ListBoxItem">
                    <Setter Property="HorizontalAlignment" Value="Center"/>
                    <Setter Property="VerticalAlignment" Value="Center"/>
                    <Style.Triggers>
                        <Trigger Property="IsSelected" Value="True">
                            <Setter Property="Foreground" Value="Green"/>
                            <Setter Property="Height" Value="200"/>
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </ListBox.ItemContainerStyle>
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Border BorderBrush="Cyan" BorderThickness="3" 
                            Width="{Binding DataContext.BorderWidth,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}},
                        Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}">
                        <Grid HorizontalAlignment="Stretch"
                              VerticalAlignment="Stretch">
                            <TextBlock Text="{Binding}" HorizontalAlignment="Center"
                                       VerticalAlignment="Center">
                                <TextBlock.Style>
                                    <Style TargetType="{x:Type TextBlock}">
                                        <Setter Property="Height" Value="100"/>
                                        <Setter Property="FontSize" Value="30"/>
                                        <Setter Property="Foreground" Value="Black"/>
                                        <Setter Property="HorizontalAlignment" Value="Center"/>
                                        <Setter Property="VerticalAlignment" Value="Center"/>
                                        <Style.Triggers>
                                            <DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=ListBoxItem}, Path=IsSelected}" Value="True">
                                                <Setter Property="Foreground" Value="Red"/>
                                                <Setter Property="FontSize" Value="50"/>
                                                <Setter Property="Height" Value="200"/>
                                            </DataTrigger>
                                            <Trigger Property="IsMouseOver" Value="True">
                                                <Setter Property="FontSize" Value="50"/>
                                                <Setter Property="Foreground" Value="Green"/>
                                            </Trigger>
                                        </Style.Triggers>
                                    </Style>
                                </TextBlock.Style>
                            </TextBlock>
                        </Grid>
                    </Border>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
</Window>


//cs
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Reflection.Metadata;
using System.Runtime.CompilerServices;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Utility;

namespace WpfApp9
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            var vm = new MainVM(this);
            this.DataContext=vm;
        }
    }

    public class MainVM : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler? PropertyChanged;
        public void OnPropertyChanged([CallerMemberName] string propName = "")
        {
            var handler = PropertyChanged;
            if (handler!=null)
            {
                handler?.Invoke(this, new PropertyChangedEventArgs(propName));
            }
        }

        private Window win;
        ListBox lbx;

        public MainVM(Window winValue)
        {
            win=winValue;
            if (win!=null)
            {
                win.Loaded+=Win_Loaded;
            }
        }

        private void Win_Loaded(object sender, RoutedEventArgs e)
        {
            var temp = win.FindName("lbx") as ListBox;
            if (temp!=null)
            {
                lbx=temp;
                BorderWidth=win.ActualWidth;
                _=InitDataAsync();

                //Task.Run(async () =>
                //{
                //   await InitDataAsync();
                //});
            }
        }

        private async Task InitDataAsync()
        {
            try
            {
                TimeGuidCollection=new ObservableCollection<string>();
                while (true)
                {
                    var newStr = await Task.Run(() => Utility.StringUtility.GetTimeAndGuid());
                    Application.Current.Dispatcher.Invoke(() =>
                    {
                        TimeGuidCollection.Add(newStr);
                        SelectedIdx=TimeGuidCollection.Count-1;
                        lbx.SelectedItem=lbx.Items[lbx.Items.Count-1];
                        lbx.ScrollIntoView(lbx.Items[lbx.Items.Count-1]);
                        SelectedStr=TimeGuidCollection[SelectedIdx];
                    });
                    await Task.Delay(1000);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private ObservableCollection<string> timeGuidCollection;
        public ObservableCollection<string> TimeGuidCollection
        {
            get
            {
                return timeGuidCollection;
            }
            set
            {
                timeGuidCollection=value;
                OnPropertyChanged();
            }
        }

        private int selectedIdx;
        public int SelectedIdx
        {
            get
            {
                return selectedIdx;
            }
            set
            {
                if (value!=selectedIdx)
                {
                    selectedIdx= value;
                    OnPropertyChanged();
                }
            }
        }

        private double borderWidth;
        public double BorderWidth
        {
            get
            {
                return borderWidth;
            }
            set
            {
                if (value!=borderWidth)
                {
                    borderWidth= value;
                    OnPropertyChanged();
                }
            }
        }

        private string selectedStr;
        public string SelectedStr
        {
            get
            {
                return selectedStr;
            }
            set
            {
                if (value!=selectedStr)
                {
                    selectedStr=value;
                    OnPropertyChanged();
                }
            }
        }
    }
}

 

 

 

 

 

 

posted @ 2025-07-19 14:07  FredGrit  阅读(5)  评论(0)    收藏  举报