WPF ControlTemplate DI Via Microsoft.Extensions.DependencyInjection

Install-Package Microsoft.Extensions.DependencyInjection;
Install-Package CommunityToolkit.mvvm;

 

 

//app.xaml
<Application x:Class="WpfApp21.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:WpfApp21">
    <Application.Resources>
         
    </Application.Resources>
</Application>


//app.xaml.cs
using Microsoft.Extensions.DependencyInjection;
using System.Windows;

namespace WpfApp21
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : Application
    {
        ServiceProvider serviceProvider;
        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);
            var services=new ServiceCollection();
            ConfigureServices(services);
            serviceProvider = services.BuildServiceProvider();

            var mainWin = serviceProvider.GetRequiredService<MainWindow>();
            mainWin?.Show();
        }

        private void ConfigureServices(ServiceCollection services)
        {
            services.AddSingleton<INameService, NameService>();
            services.AddSingleton<IISBNService, ISBNService>();
            services.AddSingleton<IPriceService, PriceService>();
            services.AddSingleton<MainVM>();
            services.AddSingleton<MainWindow>();
        }

        protected override void OnExit(ExitEventArgs e)
        {
            base.OnExit(e);
            serviceProvider?.Dispose();
        }
    }

}


//MainWindow.xaml
<Window x:Class="WpfApp21.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"
        WindowState="Maximized"
        xmlns:local="clr-namespace:WpfApp21"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <!--DataTemplate for ListBox items-->
        <DataTemplate x:Key="ItemTemplate">
            <Border Background="#FFE3F2FD"
                    CornerRadius="0"
                    Padding="10"
                    Margin="2">
                <StackPanel Width="{Binding DataContext.GridWidth,RelativeSource={RelativeSource AncestorType=Window}}"
                            Height="{Binding DataContext.GridHeight,RelativeSource={RelativeSource AncestorType=Window}}">
                    <TextBlock Text="{Binding Name}" FontWeight="Bold" FontSize="50"/>
                    <TextBlock Text="{Binding ISBN}" FontSize="40" TextWrapping="Wrap"/>
                    <TextBlock Text="{Binding Price,StringFormat='C'}"
                               Foreground="Green" FontWeight="Bold"  FontSize="40" Margin="0,5,0,0"/>
                </StackPanel>
            </Border>
        </DataTemplate>
        
        <!--Custom ControlTemplate for ListBox-->
        <ControlTemplate x:Key="lbxControlTemplate"
                         TargetType="{x:Type ListBox}">
            <Border Background="{TemplateBinding Background}"
                    BorderBrush="{TemplateBinding BorderBrush}"
                    BorderThickness="{TemplateBinding BorderThickness}"
                    CornerRadius="10">
                <ScrollViewer Padding="{TemplateBinding Padding}"
                              Focusable="False">
                    <ItemsPresenter/>
                </ScrollViewer>
            </Border>
        </ControlTemplate>
        
        <!--Style for ListBox-->
        <Style x:Key="CustomListBoxStyle"
               TargetType="{x:Type ListBox}">
            <Setter Property="Template" Value="{StaticResource lbxControlTemplate}"/>
            <Setter Property="Background" Value="#FFF5F5F5"/>
            <Setter Property="BorderBrush" Value="#FFBDBDBD"/>
            <Setter Property="BorderThickness" Value="1"/>
            <Setter Property="Padding" Value="5"/>
            <!--<Setter Property="ScrollViewer.HorizontalBarVisibity" Value="Auto"/>
            <Setter Property="ScrollViewer.VerticalBarVisibility" Value="Auto"/>-->
            <Setter Property="ScrollViewer.CanContentScroll" Value="True"/>
            <Setter Property="VerticalContentAlignment" Value="Stretch"/>
            <Setter Property="ItemTemplate" Value="{StaticResource ItemTemplate}"/>
            <Style.Triggers>
                <Trigger Property="ItemsControl.AlternationIndex" Value="0">
                    <Setter Property="Background" Value="#FFF5F5F5"/>
                </Trigger>
                <Trigger Property="ItemsControl.AlternationIndex" Value="1">
                    <Setter Property="Background" Value="#FFFFFFFF"/>
                </Trigger>
            </Style.Triggers>
        </Style>
        
        <!--Style for ListBoxItem-->
        <Style TargetType="{x:Type ListBoxItem}">
            <Setter Property="SnapsToDevicePixels" Value="True"/>
            <Setter Property="Padding" Value="4,2"/>
            <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
            <Setter Property="VerticalContentAlignment" Value="Stretch"/>
            <Setter Property="Background" Value="Transparent"/>
            <Setter Property="BorderBrush" Value="Transparent"/>
            <Setter Property="BorderThickness" Value="1"/>
            <Setter Property="FocusVisualStyle" Value="{x:Null}"/>

            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ListBoxItem}">
                        <Border x:Name="Bd"
                                Background="{TemplateBinding Background}"
                                BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="{TemplateBinding BorderThickness}"
                                CornerRadius="6"
                                SnapsToDevicePixels="True">
                            <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                              VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                              SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                        </Border>

                        <ControlTemplate.Triggers>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter TargetName="Bd" Property="Background" Value="#FFBBDEFB"/>
                                <Setter TargetName="Bd" Property="BorderBrush" Value="#FF64B5F6"/>
                            </Trigger>

                            <Trigger Property="IsSelected"  Value="True">
                                <Setter TargetName="Bd"  Property="Background" Value="#FF2196F3"/>
                                <Setter TargetName="Bd" Property="BorderBrush" Value="#FF1976D2"/>
                            </Trigger>
                            <MultiTrigger>
                                <MultiTrigger.Conditions>
                                    <Condition Property="IsSelected" Value="True"/>
                                    <Condition Property="IsMouseOver" Value="True"/>
                                </MultiTrigger.Conditions>
                                <Setter TargetName="Bd" Property="Background" Value="#FF1976D2"/>
                                <Setter TargetName="Bd" Property="BorderBrush" Value="#FF0D47A1"/>
                            </MultiTrigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>
    <Grid>
        <ListBox x:Name="customLbx"
             Style="{StaticResource CustomListBoxStyle}"
             ItemsSource="{Binding BooksCollection,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
             SelectionMode="Extended"
             Margin="20">           
        </ListBox>
    </Grid>
</Window>


//MainWindow.xaml.cs
using CommunityToolkit.Mvvm.ComponentModel;
using System.Collections.ObjectModel;
using System.Windows;

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

        public MainWindow(MainVM vm)
        {
            InitializeComponent();
            this.DataContext=vm;
            this.SizeChanged+=MainWindow_SizeChanged;
        }

        private void MainWindow_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            if (this.DataContext is MainVM vm)
            {
                var fe = this.Content as FrameworkElement;
                if (fe!=null)
                {
                    vm.GridWidth=fe.ActualWidth;
                    vm.GridHeight=fe.ActualHeight/5;
                }
            }
        }
    }

    public partial class MainVM : ObservableObject
    {

        private INameService nameService;
        private IISBNService isbnService;
        private IPriceService priceService;
        public MainVM(INameService nameServiceValue, IISBNService isbnServiceValue, IPriceService priceServiceValue)
        {
            nameService= nameServiceValue;
            isbnService= isbnServiceValue;
            priceService= priceServiceValue;
            InitItems();
        }

        private void InitItems()
        {
            BooksCollection=new ObservableCollection<Book>();
            for (int i = 0; i<100; i++)
            {
                BooksCollection.Add(new Book()
                {
                    Name=nameService.GetName(),
                    ISBN=isbnService.GetISBN(),
                    Price=priceService.GetPrice()
                });
            }
        }

        [ObservableProperty]
        private ObservableCollection<Book> booksCollection;

        [ObservableProperty]
        private double gridWidth;

        [ObservableProperty]
        private double gridHeight;
    }

    public class Book
    {
        public string Name { get; set; }
        public string ISBN { get; set; }
        public decimal Price { get; set; }
    }

    public interface INameService
    {
        string GetName();
    }

    public class NameService : INameService
    {
        int idx = 0;
        public string GetName()
        {
            return $"Name_{Interlocked.Increment(ref idx)}";
        }
    }

    public interface IISBNService
    {
        string GetISBN();
    }

    public class ISBNService : IISBNService
    {
        int idx = 0;
        public string GetISBN()
        {
            return $"ISBN_{Interlocked.Increment(ref idx)}_{Guid.NewGuid():N}";
        }
    }

    public interface IPriceService
    {
        decimal GetPrice();
    }

    public class PriceService : IPriceService
    {
        Random rnd = new Random();
        public decimal GetPrice()
        {
            return (decimal)rnd.NextDouble()*100;
        }
    }

}

 

 

 

 

 

 

 

 

 

 

 

image

 

 

 

 

image

 

posted @ 2025-09-18 19:06  FredGrit  阅读(9)  评论(0)    收藏  举报