简体   繁体   中英

How do I dynamically change a scrollbar background image in WPF?

This question is brutally difficult to ask in a clear fashion. But, I am going to try my best...

In the title, "scrollbar background" means the track area as shown in the following image (blatantly stolen from https://www.codeproject.com/Articles/41787/Creating-a-Blend-like-Scrollbar ).

Parts of a scrollbar

Apparently, stackoverflow will not allow me to embed images. So I hope the above link works.

Also, the word "dynamically" in the title does not mean swapping out one resource image for another. It means, create an image in memory and assign it to the scrollbar at run time.

I put together a simple project to demonstrate what I am trying to do. Here's a screenshot.

Screenshot of desired effect

Wait! Stop. Please don't suggest I "process out" to a third party app like Winmerge or whatever. Remember, this is just a demo app to help get the idea across. My real app is not comparing text files, although the end result will be very similar.

Here's s bit of the XAML of my demo app.

<Grid>
    <DataGrid Name="dgDiffs" AutoGenerateColumns="False">
        <DataGrid.Resources>
            <Style TargetType="ScrollBar">
                <Setter Property="Background">
                    <Setter.Value>
                        <!--<ImageBrush ImageSource="{Binding overview}" />-->
                        <ImageBrush ImageSource="overview.png" />
                    </Setter.Value>

As you can see, I have hard coded an image for the demo (overview.png). You can also see where I tried to bind the image source to an object in C#. The idea being that I programmatically create a bitmap showing the overview, and then update the scrollbar.

And this is where I am stuck. I have tried creating simple bitmap objects and filling them with solid colors, but they do not appear on my scrollbar. I'm not even sure that I am taking the right approach.

Here's my demo code trying to use a bitmap object.

public partial class MainWindow : Window {

    class DiffItem {
        public int diff { get; set; } // used to color grid row (highlight differences)
        public string leftString { get; set; }
        public string rightString { get; set; }
    }

    public MainWindow() {
        InitializeComponent();

        // build a lengthy list for demonstration
        List<DiffItem> diffList = new List<DiffItem>();
        for (int i = 0; i < 10; i++) {
            // I've chopped out a bunch of lines here. This just builds a long repeating list for the demo
            diffList.Add(new DiffItem() { diff = 0, leftString = "one", rightString = "one" });
            diffList.Add(new DiffItem() { diff = -1, leftString = "four", rightString = "" });
            diffList.Add(new DiffItem() { diff = 1, leftString = "", rightString = "eight" });
            diffList.Add(new DiffItem() { diff = 2, leftString = "eleven", rightString = "elven" });
            diffList.Add(new DiffItem() { diff = 0, leftString = "sixteen", rightString = "sixteen" });
        }

        // display list
        dgDiffs.ItemsSource = diffList;

        // update scrollbar overview
        Bitmap overview = new Bitmap(20, 200);
        using (Graphics g = Graphics.FromImage(overview)) {
            g.Clear(Color.Green);
        }
    }
}

And here's the XAML trying to bind the scrollbar's image source.

<Grid>
    <DataGrid Name="dgDiffs" AutoGenerateColumns="False">
        <DataGrid.Resources>
            <Style TargetType="DataGridRow">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding diff}" Value="2">
                        <Setter Property="Background" Value="Orange" />
                    </DataTrigger>
                    <DataTrigger Binding="{Binding diff}" Value="1">
                        <Setter Property="Background" Value="LightGreen" />
                    </DataTrigger>
                    <DataTrigger Binding="{Binding diff}" Value="-1">
                        <Setter Property="Background" Value="OrangeRed" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
            <Style TargetType="ScrollBar">
                <Setter Property="Background">
                    <Setter.Value>
                        <ImageBrush ImageSource="{Binding overview}" />
                        <!--<ImageBrush ImageSource="overview.png" />-->
                    </Setter.Value>
                </Setter>
            </Style>
        </DataGrid.Resources>
        <DataGrid.Columns>
            <DataGridTextColumn Binding="{Binding leftString}" Width="200"></DataGridTextColumn>
            <DataGridTextColumn Binding="{Binding rightString}" Width="*"></DataGridTextColumn>
        </DataGrid.Columns>
    </DataGrid>
</Grid>

In case anyone is wondering... this is how to do it.

XAML

<Grid>
    <DataGrid Name="dgDiffs" AutoGenerateColumns="False">
        <DataGrid.Resources>
            <Style TargetType="DataGridRow">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding diff}" Value="2">
                        <Setter Property="Background" Value="Orange" />
                    </DataTrigger>
                    <DataTrigger Binding="{Binding diff}" Value="1">
                        <Setter Property="Background" Value="LightGreen" />
                    </DataTrigger>
                    <DataTrigger Binding="{Binding diff}" Value="-1">
                        <Setter Property="Background" Value="OrangeRed" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
            <Style TargetType="ScrollBar">
                <Setter Property="Background">
                    <Setter.Value>
                        <ImageBrush ImageSource="{Binding Path=overview}" />
                        <!--<ImageBrush ImageSource="overview.png" />-->
                    </Setter.Value>
                </Setter>
            </Style>
        </DataGrid.Resources>
        <DataGrid.Columns>
            <DataGridTextColumn Binding="{Binding leftString}" Width="200"></DataGridTextColumn>
            <DataGridTextColumn Binding="{Binding rightString}" Width="*"></DataGridTextColumn>
        </DataGrid.Columns>
    </DataGrid>
</Grid>

C#

public partial class MainWindow : Window {

    class DiffItem {
        public int diff { get; set; } // used to color grid row (highlight differences)
        public string leftString { get; set; }
        public string rightString { get; set; }
    }

    public BitmapImage overview { get; set; }

    public MainWindow() {
        InitializeComponent();
        DataContext = this;

        // build a lengthy list for demonstration
        List<DiffItem> diffList = new List<DiffItem>();
        for (int i = 0; i < 10; i++) {
            diffList.Add(new DiffItem() { diff = 0, leftString = "one", rightString = "one" });
            diffList.Add(new DiffItem() { diff = 0, leftString = "two", rightString = "two" });
            diffList.Add(new DiffItem() { diff = 0, leftString = "three", rightString = "three" });
            diffList.Add(new DiffItem() { diff = -1, leftString = "four", rightString = "" });
            diffList.Add(new DiffItem() { diff = 0, leftString = "five", rightString = "five" });
            diffList.Add(new DiffItem() { diff = 0, leftString = "six", rightString = "six" });
            diffList.Add(new DiffItem() { diff = 0, leftString = "seven", rightString = "seven" });
            diffList.Add(new DiffItem() { diff = 1, leftString = "", rightString = "eight" });
            diffList.Add(new DiffItem() { diff = 0, leftString = "nine", rightString = "nine" });
            diffList.Add(new DiffItem() { diff = 0, leftString = "ten", rightString = "ten" });
            diffList.Add(new DiffItem() { diff = 2, leftString = "eleven", rightString = "elven" });
            diffList.Add(new DiffItem() { diff = 2, leftString = "twelv", rightString = "twelve" });
            diffList.Add(new DiffItem() { diff = 0, leftString = "thirteen", rightString = "thirteen" });
            diffList.Add(new DiffItem() { diff = 0, leftString = "fourteen", rightString = "fourteen" });
            diffList.Add(new DiffItem() { diff = 0, leftString = "fifteen", rightString = "fifteen" });
            diffList.Add(new DiffItem() { diff = 0, leftString = "sixteen", rightString = "sixteen" });
        }

        // display list
        dgDiffs.ItemsSource = diffList;

        // create the overview bitmap
        Bitmap bmp = new Bitmap(20, 200, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
        using (Graphics g = Graphics.FromImage(bmp)) {
            Pen greenPen = new Pen(Color.Green, 1);
            g.Clear(Color.White);
            g.DrawLine(greenPen, 0, 50, 20, 50);
        }
        MemoryStream memoryStream = new MemoryStream();
        bmp.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Bmp);

        // load scrollbar with overview
        overview = new BitmapImage();
        overview.BeginInit();
        overview.StreamSource = memoryStream;
        overview.EndInit();
        overview.Freeze();
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM