How to change all items in the ListBox - c#

I use DataTemplate to repeatedly generate the content of my ListBox.
The xaml code is as below:
<DataTemplate x:Key="singleUnit">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding fileName}" FontSize="20" Foreground="{Binding color}" HorizontalAlignment="Left" VerticalAlignment="Top"/>
<TextBlock/>
</StackPanel>
</DataTemplate>
<ListBox Name="MyListBox" Width="300" Height="600">
</ListBox>
And the cs code is:
private void Show()
{
const int TotalCount = 100;
for (int i = 0; i < TotalCount; i++)
{
ContentControl cc = new ContentControl();
cc.ContentTemplate = this.Resources["singleUnit"] as DataTemplate;
DataModel dm = new DataModel();
dm.fileName = "myfile" + i;
dm.color = new SolidColorBrush(Colors.Blue);
cc.Content = dm;
MyListBox.Items.Add(cc);
}
MyListBox.ScrollIntoView(MyListBox.Items[TotalCount / 2]);
}
Above code will generate below UI:
And I hope to change all the item's color: currently each item, the fileName's foreground color is blue. And I hope to change it to like green when the button is pressed.
This is like that user changes the color theme with some selection operation. And when the color changes, all the other things should be not changed, e.g. the position of the scroll bar.
The difficulty is that I use template to generate the content, and how to iterate each item and modify it.
I put the workable demo code on my Github:
https://github.com/tomxue/ChangeListBox.git
You could start from it.
Thanks!

I made your code work but it is still not perfectly right as you should have per each view a view-model and bind between them.
Your MainForm - should have a MainFormViewModel.
Your File Items - should have VmFile (or ViewModelFile as I wrote in the example)
You should be using ICommand to bind the button and not by having an event as you did.
Shortly put, I don't think you are working correct with MVVM, I advise you to read more about MVVM.
Copy to your .xaml file:
<Window x:Class="WpfApp14.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:WpfApp14"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<ListBox Name="MyListBox" Width="300" Height="600">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding FileName}" FontSize="20" Foreground="{Binding Color}"
HorizontalAlignment="Left" VerticalAlignment="Top"/>
<TextBlock/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button Content="Change color theme" HorizontalAlignment="Left" Margin="56,126,0,0" VerticalAlignment="Top" Width="164" Click="Button_Click" Height="36"/>
</Grid>
</Window>
Copy to your .cs file:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
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;
namespace WpfApp14
{
public class ViewModelFile : INotifyPropertyChanged
{
private string filename;
private SolidColorBrush solidColorBrush;
public event PropertyChangedEventHandler PropertyChanged;
public string FileName
{
get =>filename;
set
{
filename = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(FileName)));
}
}
public SolidColorBrush Color
{
get => solidColorBrush;
set
{
solidColorBrush = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Color)));
}
}
}
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Refresh();
}
private void Refresh()
{
const int TotalCount = 100;
for (int i = 0; i < TotalCount; i++)
{
ViewModelFile vm = new ViewModelFile
{
FileName = "myfile" + i,
Color = new SolidColorBrush(Colors.Blue)
};
MyListBox.Items.Add(vm);
}
MyListBox.ScrollIntoView(MyListBox.Items[TotalCount / 2]);
}
private void Button_Click(object sender, RoutedEventArgs e)
{
// Do something to change all fileName items' forground color to red.
// For example if user changes the color theme, and we should just change some UI color
// while not changing any other part, e.g. the position of scrollbar
foreach (var item in MyListBox.Items)
((ViewModelFile)item).Color = new SolidColorBrush(Colors.Red);
}
}
}

Related

How do I save ITheme of Material Design in a text file for saving color theme chosen in C# WPF?

I'm using Material design. I created a color picker to choose the color the user wants, after the user chooses the color and theme.
I want to save these settings into a text file on the disk. I don't know how can I convert these types to a list for the string which can I use for reading theme that is saved :
private void MyColorPicker1_PreviewMouseMove(object sender, MouseEventArgs e)
{
string filepath = #"C:\Themses";
if (e.LeftButton == MouseButtonState.Pressed)
{
ITheme theme = _paletteHelper.GetTheme();
theme.SetPrimaryColor(Color.FromRgb(MyColorPicker1.Color.R, MyColorPicker1.Color.G, MyColorPicker1.Color.B)); //red
var Test = theme.GetBaseTheme();
// something here to write all setting inside of ITheme into the text file
//
_paletteHelper.SetTheme(theme);
}
}
How can I do that?
Full XAML:
<Window x:Class="WpfApp5.SettingThemsWins.MaterialThemSettingy"
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:WpfApp5.SettingThemsWins"
mc:Ignorable="d"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
Background="{DynamicResource MaterialDesignPaper}"
Title="Setting" Height="607" Width="1144" WindowStartupLocation="CenterScreen">
<Grid>
<materialDesign:ColorPicker x:Name="MyColorPicker1" HorizontalAlignment="Left" Margin="20,17,0,0" VerticalAlignment="Top" Height="353" Width="750" PreviewMouseMove="MyColorPicker1_PreviewMouseMove" />
<ToggleButton x:Name="ThemeActivationsBtn" Style="{StaticResource MaterialDesignSwitchToggleButton}" ToolTip="Activation Of Dark Theme" IsChecked="False" Margin="110,380,0,0" Click="ThemeActivationsBtn_Click" HorizontalAlignment="Left" Width="63" Height="27" VerticalAlignment="Top" />
<Label Content="Dark Theme :" HorizontalAlignment="Left" Height="24" Margin="20,382,0,0" VerticalAlignment="Top" Width="85"/>
<Button x:Name="SaverThemy" Content="Save Theme" HorizontalAlignment="Left" Margin="200,375,0,0" VerticalAlignment="Top" Width="170" Click="SaverThemy_Click"/>
</Grid>
</Window>
Code behind:
using MaterialDesignThemes.Wpf;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
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.Shapes;
namespace WpfApp5.SettingThemsWins
{
/// <summary>
/// Interaction logic for MaterialThemSettingy.xaml
/// </summary>
public partial class MaterialThemSettingy : Window
{
private readonly PaletteHelper _paletteHelper = new PaletteHelper();
bool isDark;
public MaterialThemSettingy()
{
InitializeComponent();
//EmptySampleWind.Window1 window1 = new EmptySampleWind.Window1();
//window1.Show();
}
public static IEnumerable<string> SortByLength(IEnumerable<string> e)
{
// Use LINQ to sort the array received and return a copy.
var sorted = from s in e
orderby s.Length ascending
select s;
return sorted;
}
private void MyColorPicker1_PreviewMouseMove(object sender, MouseEventArgs e)
{
string filepath = #"C:\Themses";
if (e.LeftButton == MouseButtonState.Pressed)
{
ITheme theme = _paletteHelper.GetTheme();
theme.SetPrimaryColor(Color.FromRgb(MyColorPicker1.Color.R, MyColorPicker1.Color.G, MyColorPicker1.Color.B)); //red
var Test = theme.GetBaseTheme();
// something here to write all setting inside of ITheme into the text file
//
_paletteHelper.SetTheme(theme);
}
}
private void ThemeActivationsBtn_Click(object sender, RoutedEventArgs e)
{
isDark = (bool)ThemeActivationsBtn.IsChecked;
if (isDark)
{
ITheme theme = _paletteHelper.GetTheme();
IBaseTheme baseTheme = isDark ? new MaterialDesignDarkTheme() : (IBaseTheme)new MaterialDesignLightTheme();
theme.SetBaseTheme(baseTheme);
_paletteHelper.SetTheme(theme);
}
else
{
ITheme theme = _paletteHelper.GetTheme();
IBaseTheme baseTheme = isDark ? new MaterialDesignDarkTheme() : (IBaseTheme)new MaterialDesignLightTheme();
theme.SetBaseTheme(baseTheme);
_paletteHelper.SetTheme(theme);
}
}
}
}

Draw graphs - show only single points

(C # Application for WPF)
I have a problem and I have to "draw" a coordinate system and enter only the coordinates (without lines) as seen in the picture.
I would like to use a library, because I also have to draw a frame and I thought with a library would it be easy.
So I've discovered GnuPlot, Oxyplot and draw myself. GnuPlot is unfortunately stupid since it has no library for a C # application. (Or if you have one, please let me know). Therefore, I used OxyPlot, but unfortunately OxyPlot shows me only the coordinate system.
Now to my question.
Is there anything better to draw coordinate systems with the coordinates?
It should meet the following requirements:
It should be a preview application, that is, if I change the size it should happen directly
I would like to make a frame, so it should help me in the process
there should be a library
it should be for a C # application
I would like to be first point marks for the X, Y coordinates, but later it should be circles with a circle diameter
later as a Bitmap
As mentioned above, I've used it with OxyPlot, but unfortunately it does not draw a graph (I used the sample documentation)
Maybe you have better ideas / a solution for OxyPlot.
Thanks in advance and I am happy about every reply.
XAML:
<Window x:Class="TestOxyPlot.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:oxy="http://oxyplot.org/wpf"
xmlns:local="clr-namespace:TestOxyPlot"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<oxy:Plot x:Name="oxyPlot" Title="{Binding Title}" Margin="207,53,0,0">
<oxy:Plot.Series>
<oxy:LineSeries ItemsSource="{Binding Points}"/>
</oxy:Plot.Series>
</oxy:Plot>
<TextBox x:Name="textBox" HorizontalAlignment="Left" Height="23" Margin="44,64,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120" MouseLeave="textBox_MouseLeave" TextChanged="textBox_TextChanged"/>
<TextBox x:Name="textBox1" HorizontalAlignment="Left" Height="23" Margin="44,101,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120" TextChanged="textBox1_TextChanged"/>
<Button x:Name="button" Content="Button" HorizontalAlignment="Left" Margin="68,174,0,0" VerticalAlignment="Top" Width="75" Click="button_Click"/>
</Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
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 OxyPlot;
namespace TestOxyPlot
{
/// <summary>
/// Interaktionslogik für MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.Title = "Example 2";
this.Points = new List<DataPoint>
{
new DataPoint(0, 4),
new DataPoint(10, 13),
new DataPoint(20, 15),
new DataPoint(30, 16),
new DataPoint(40, 12),
new DataPoint(50, 12)
};
}
public string Title { get; private set; }
public IList<DataPoint> Points { get; private set; }
private void textBox_MouseLeave(object sender, MouseEventArgs e)
{
}
private void textBox_TextChanged(object sender, TextChangedEventArgs e)
{
try
{
oxyPlot.Width = Int32.Parse(textBox.Text);
}
catch (Exception error)
{
MessageBox.Show("Message: " + error);
}
}
private void button_Click(object sender, RoutedEventArgs e)
{
}
private void textBox1_TextChanged(object sender, TextChangedEventArgs e)
{
try
{
oxyPlot.Width = Int32.Parse(textBox.Text);
}
catch (Exception error)
{
MessageBox.Show("Message: " + error);
}
}
}
}
Add this code
DataContext = this;
after this line
InitializeComponent();
and it will show the graph. Also, in order to remove the line and just draw the Markers, use something like this LineSeries:
<oxy:LineSeries ItemsSource="{Binding Points}" LineStyle="None" MarkerType="Circle" MarkerSize="5" MarkerFill="Black"/>
Edit
private void Button_Click(object sender, RoutedEventArgs e)
{
double randomNumX;
double randomNumY;
int h = DateTime.Now.Hour;
int m = DateTime.Now.Minute;
int s = DateTime.Now.Second;
String u = h.ToString() + m.ToString() + s.ToString();
int iu = Int32.Parse(u);
Random zufall = new Random(iu);
Points = new List<DataPoint>();
for (int i = 0; i < 10; i++)
{
randomNumX = zufall.NextDouble() * (10 - -10) + -10;
randomNumY = zufall.NextDouble() * (10 - -10) + -10;
Points.Add(new DataPoint(randomNumX, randomNumY));
}
ls.ItemsSource = Points;
}
and
<DockPanel>
<Button DockPanel.Dock="Top" Click="Button_Click" Content="Click Me"/>
<oxy:Plot x:Name="oxyPlot" Title="{Binding Title}">
<oxy:Plot.Axes>
<oxy:LinearAxis Position="Bottom" />
<oxy:LinearAxis Position="Right" MinimumPadding="0.1" MaximumPadding="0.1"/>
</oxy:Plot.Axes>
<oxy:Plot.Series>
<oxy:LineSeries x:Name="ls" ItemsSource="{Binding Points}" LineStyle="None" MarkerType="Circle" MarkerSize="5" MarkerFill="Black"/>
</oxy:Plot.Series>
</oxy:Plot>
</DockPanel>
By the way, for some reason, using ObservationCollection or InvalidatePlot(true) didn't work

Dynamic UI Layout in DataGridCell using ItemsControl and a Button

This screenshot is from the mockup of my ideal UI. Right now, this is a DataGridTemplateColumn, with header = "ATTENDEES". I am running into issues creating the layout of this DataGridColumn's cell.
I currently have an ItemsControl bound to a List of strings which are the attendees' emails. If there are too many attendees and the ItemsControls' bounds cannot fit in the cell, then a Button with Content = "See more" should appear at the bottom of the cell, under the last attendee email that can be rendered within in the cell's bounds.
Then once the Button ("See more") is clicked, the row should expand to an appropriate height for the attendees to all be visible, and the "See more" Button should disappear.
I could not wrap my head around a clean implementation with a TemplateSelector, ValueConverter, or DataTrigger in pure XAML since I need to compare the ItemsControls' height against the DataGridRow's height and then perform a modification of the cell's layout at runtime by hiding all the items in the ItemsControl that cannot fit within the cell and then showing at Button below it.
I concluded on attempting to do this in the code-behind by subscribing to the ItemControls' load event. I first attempted to use the Height, MaxHeight, DesiredSize.Height, RenderedSize.Height, and ActualSize.Height properties of the ItemsControl but those all were equal to the clipped height of the ItemsControl, not the intrinsic height of all its contents.
I am now measuring the total height of all its items' strings using the FormattedText class. Then I compare this summed height with the row's height and that's as far as I have progressed; I am unsure of how to next change the layout of the cell or if this is even the correct approach.
I feel like I am fighting against the design of the WPF framework by doing rudimentary calculations and crude layout changes to the view in the code-behind.
Any help on this would be greatly appreciated!
Here is my event handler for the ItemsControl.Load:
private void AttendeesItemsControl_Loaded(object sender, RoutedEventArgs e)
{
if (currentRowIndex == -1)
{
return;
}
List<ModelBase> eventsData = ModelManager.events.data;
var eventObj = (Event)eventsData[currentRowIndex];
var attendees = eventObj.attendees;
var totalItemsHeight = 0;
for(int i = 0; i < attendees.Count; i++)
{
totalItemsHeight += heightOfString(attendees[i]);
}
var itemsControl = (ItemsControl)sender;
var controlRenderHeight = itemsControl.RenderSize.Height;
// Check if the intrinsic height is greater than what can be drawn inside the cell
if (controlRenderHeight < totalItemsHeight)
{
var itemHeight = totalItemsHeight / attendees.Count;
var visibleItemsCount = controlRenderHeight / itemHeight;
// .... not sure how to proceed
}
}
And the helper function that measures the height of one of its items:
private int heightOfString(string candidate)
{
var fontFamily = new FontFamily("Lato");
var fontStyle = FontStyles.Normal;
var fontWeight = FontWeights.Normal;
var fontStretch = FontStretches.Normal;
var fontSize = 12;
var typeFace = new Typeface(fontFamily, fontStyle, fontWeight, fontStretch);
var formattedText = new FormattedText(candidate, CultureInfo.CurrentUICulture, FlowDirection.LeftToRight, typeFace, fontSize, Brushes.Black);
return (int)formattedText.Height;
}
Finally, this is the DataGridTemplateColumn's XAML, with the cell template definition:
<DataGridTemplateColumn Header="ATTENDEES" Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ItemsControl ItemsSource="{Binding Path=attendees}" x:Name="AttendeesItemsControl" Loaded="AttendeesItemsControl_Loaded">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock FontFamily="Lato" FontSize="12" FontWeight="Normal" Text="{Binding}">
</TextBlock>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
I had to do some real work but I got this set up. Hopefully you can follow it. Here is a screen shot of what it looks like. Obviously i didn't attempt to style it yet. Just getting the resizing. This way you let WPF handle the height of your control you leave it autosized. You just manage your list.
I created a control for the list called AttendeeListControl
<UserControl xmlns:stackoverflow="clr-namespace:stackoverflow" x:Class="stackoverflow.AttendeeListControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid Background="GhostWhite">
<Grid.RowDefinitions>
<RowDefinition Height="37"/>
<RowDefinition Height="*"/>
<RowDefinition Height="23"/>
</Grid.RowDefinitions>
<Label Content="Attendees" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top"/>
<ListBox Name="listBoxAttendees" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.Row="1" />
<Button Content="SeeMore" Name="lblMore" HorizontalAlignment="Left" Margin="10,0,0,0" Grid.Row="2" VerticalAlignment="Top" Click="lblMore_Click"/>
</Grid>
</UserControl>
This is the code behind
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows.Controls;
namespace stackoverflow
{
/// <summary>
/// Interaction logic for AttendeeListControl.xaml
/// </summary>
///
public partial class AttendeeListControl : UserControl
{
public AttendeeListViewModel vm { get; set; }
public AttendeeListControl()
{
InitializeComponent();
var emails = new List<string>() { "email#gmail.com", "email#aol.com", "email.yahoo.com", "email#msn.com" };
var displayed = new ObservableCollection<string>() { emails[0], emails[1] };
vm = new AttendeeListViewModel()
{
EmailList = emails,
DisplayList = displayed,
Expanded = false
};
DataContext = vm;
listBoxAttendees.ItemsSource = vm.DisplayList;
}
private void lblMore_Click(object sender, System.Windows.RoutedEventArgs e)
{
if (vm.Expanded)
{
//remove all but last 2
do
{
vm.DisplayList.RemoveAt(vm.DisplayList.Count - 1);
} while (vm.DisplayList.Count > 2);
lblMore.Content = "Show More";
}
else
{
//don't want the first 2
for (int i = 2; i < vm.EmailList.Count; i++)
{
vm.DisplayList.Add(vm.EmailList[i]);
}
lblMore.Content = "Show Less";
}
vm.Expanded = !vm.Expanded;
}
}
}
and here is the model i used
using System.Collections.Generic;
using System.Collections.ObjectModel;
namespace stackoverflow
{
public class AttendeeListViewModel
{
public bool Expanded { get; set; }
public List<string> EmailList { get; set; }
public ObservableCollection<string> DisplayList { get; set; }
}
}
this was all just put on the mainwindow
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:stackoverflow" x:Class="stackoverflow.MainWindow"
Title="MainWindow" Height="350" Width="525">
<Grid>
<local:AttendeeListControl HorizontalAlignment="Left" Margin="55,53,0,0" VerticalAlignment="Top"/>
<local:AttendeeListControl HorizontalAlignment="Left" Margin="340,53,0,0" VerticalAlignment="Top"/>
</Grid>
</Window>

C# WPF image load like progressbar

I'v a progressbar and an image.
When Progress Bar value is 50, image loaded by 50%.
I tried to add image as the progressbar foreground, but it have green shade. So ugly.
How can I do this?
To run this sample, you need a snake image which you can get from http://res.freestockphotos.biz/pictures/16/16242-illustration-of-a-green-snake-pv.png. I have used this url directly, but your should download image first and then use it.
You need a control template for your ProgressBar because you want to show percentage status too.
Otherwise normal ProgressBar would do.
Code can be used as is :
<Window x:Class="WpfControlTemplates._32794074.Win32794074"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Win32794074" Height="600" Width="1000">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="397*"/>
<RowDefinition Height="173*"/>
</Grid.RowDefinitions>
<ProgressBar x:Name="PBarCustom" Width="958" Height="200" Maximum="958" Value="958" Foreground="#FFE6E61F" Margin="17,185,17,11.932" ValueChanged="PBarCustom_ValueChanged">
<ProgressBar.Background>
<ImageBrush ImageSource="http://res.freestockphotos.biz/pictures/16/16242-illustration-of-a-green-snake-pv.png"/>
</ProgressBar.Background>
<ProgressBar.Template>
<ControlTemplate>
<Grid Background="{TemplateBinding Background}">
<Rectangle x:Name="Thumb" HorizontalAlignment="Left" Fill="#FFC5EA1F" Stroke="#FF0DB442" Width="{TemplateBinding Width}" />
<Ellipse Fill="#FF7DEEDE" Height="124" Stroke="#FF0DB442" Width="150" VerticalAlignment="Center" HorizontalAlignment="Center" Opacity="0.3"/>
<Label x:Name="tbStatus" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" FontWeight="Bold" FontSize="75" Foreground="#FF21BD76" Content="0" />
</Grid>
</ControlTemplate>
</ProgressBar.Template>
</ProgressBar>
<Button x:Name="BtnLoadSnake" Content="Load Snake" HorizontalAlignment="Left" Margin="462,14.068,0,0" VerticalAlignment="Top" Width="75" Click="BtnLoadSnake_Click" Grid.Row="1"/>
</Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
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.Shapes;
using System.Windows.Threading;
namespace WpfControlTemplates._32794074
{
/// <summary>
/// Interaction logic for Win32794074.xaml
/// </summary>
public partial class Win32794074 : Window
{
public Win32794074()
{
InitializeComponent();
}
DispatcherTimer timer;
private void BtnLoadSnake_Click(object sender, RoutedEventArgs e)
{
BtnLoadSnake.IsEnabled = false;
PBarCustom.Value = PBarCustom.Maximum;
Rectangle thumb = (Rectangle)PBarCustom.Template.FindName("Thumb", PBarCustom);
thumb.Width = PBarCustom.Value;
Label status = (Label)PBarCustom.Template.FindName("tbStatus", PBarCustom);
status.Content = ((int)(100 - ((100 * PBarCustom.Value) / PBarCustom.Maximum))).ToString();
Dispatcher disp = PBarCustom.Dispatcher;
EventHandler pBarCallbackHandler = new EventHandler(pBarCallback);
timer = new DispatcherTimer(TimeSpan.FromSeconds(0.5), DispatcherPriority.Normal, pBarCallback, disp);
}
private void pBarCallback(object sender, EventArgs e)
{
PBarCustom.Value -= 13;
Rectangle thumb = (Rectangle)PBarCustom.Template.FindName("Thumb", PBarCustom);
thumb.Width = PBarCustom.Value;
Label status = (Label)PBarCustom.Template.FindName("tbStatus", PBarCustom);
status.Content = ((int)(100 - ((100 * PBarCustom.Value) / PBarCustom.Maximum))).ToString();
if (PBarCustom.Value == 0)
timer.Stop();
}
private void PBarCustom_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if(e.NewValue == 0)
BtnLoadSnake.IsEnabled = true;
}
}
}
i had similar scenario.
if you want the scroll bar to be just a rectangle,
easiest way to make it:
1- add an image to your window.
2- put a grid on it in such a way that the grid hides the image.
3- programatically change the width or height of the grid.
tell me if you needed an example code.

WPF image inside border is not fully drawn

I have an image within a border:
XAML:
<Window x:Class="TestProgram.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Test" Height="350" Width="525">
<DockPanel>
<Grid DockPanel.Dock="Top">
<!---->
</Grid>
<ListBox DockPanel.Dock="Left"/>
<Grid DockPanel.Dock="Top">
<!---->
</Grid>
<Border x:Name="testBorder" ClipToBounds="True" Background="Gray">
<Image x:Name="testImage" Source="test.png" Opacity="1" Stretch="None"
MouseLeftButtonDown="testImage_MouseLeftButtonDown"
MouseLeftButtonUp="testImage_MouseLeftButtonUp"
MouseMove="testImage_MouseMove"
/>
</Border>
</DockPanel>
</Window>
C#:
using System;
using System.Collections.Generic;
using System.Linq;
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;
namespace TestProgram
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private Point start;
private Point origin;
public MainWindow()
{
InitializeComponent();
TransformGroup group = new TransformGroup();
TranslateTransform tt = new TranslateTransform();
group.Children.Add(tt);
testImage.RenderTransform = group;
}
private void testImage_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
testImage.CaptureMouse();
TranslateTransform tt = (TranslateTransform)((TransformGroup)testImage.RenderTransform).Children.First(tr => tr is TranslateTransform);
start = e.GetPosition(testBorder);
origin = new Point(tt.X, tt.Y);
}
private void testImage_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
testImage.ReleaseMouseCapture();
}
private void testImage_MouseMove(object sender, MouseEventArgs e)
{
if (testImage.IsMouseCaptured)
{
TranslateTransform tt = (TranslateTransform)((TransformGroup)testImage.RenderTransform).Children.First(tr => tr is TranslateTransform);
Vector v = start - e.GetPosition(testBorder);
tt.X = origin.X - v.X;
tt.Y = origin.Y - v.Y;
}
}
}
}
I have added click & drag panning functionality, but the displayed size of the image is limited by the surrounding border, leaving only the top left corner of the image visible when the image is panned. This is the case even when i remove ClipToBounds="True"
ActualHeight and ActualWidth have values corresponding to the image's natural height and width, so why is the image clipped? What can I do to make the full image visible?
If you really want the border to overlay on top of the the image, then put them both in a <Grid> or <Canvas>
<Canvas>
<Image/>
<Borde/>
</Canvas>

Categories

Resources