Fixed Wrap panel wpf - wpf

i am working on wpf window that show list of items next each other with wrapping, i have tried to use WrapPanel in this way:
<Grid>
<ItemsControl>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.Items>
<Button Content="01" Height="30" Width="70"/>
<Button Content="02" Height="35" Width="72"/>
<Button Content="03" Height="20" Width="74"/>
<Button Content="04" Height="25" Width="76"/>
<Button Content="05" Height="18" Width="78"/>
<Button Content="06" Height="50" Width="70"/>
<Button Content="07" Height="40" Width="72"/>
<Button Content="08" Height="55" Width="74"/>
<Button Content="09" Height="45" Width="76"/>
<Button Content="10" Height="25" Width="78"/>
<Button Content="11" Height="20" Width="80"/>
<Button Content="12" Height="30" Width="70"/>
<Button Content="13" Height="45" Width="72"/>
<Button Content="14" Height="30" Width="74"/>
<Button Content="15" Height="20" Width="76"/>
<Button Content="16" Height="25" Width="78"/>
<Button Content="17" Height="35" Width="80"/>
<Button Content="18" Height="50" Width="70"/>
<Button Content="19" Height="55" Width="72"/>
<Button Content="20" Height="45" Width="74"/>
<Button Content="21" Height="20" Width="76"/>
<Button Content="22" Height="60" Width="78"/>
<Button Content="23" Height="20" Width="80"/>
<Button Content="24" Height="25" Width="70"/>
<Button Content="25" Height="30" Width="72"/>
</ItemsControl.Items>
</ItemsControl>
</Grid>
and this is the result:
Actually this result is unsatisfactory for me because if you imagine the WrapPanel as grid(rows and columns) you will find that there is no columns, but there are fixed size rows. i need to make WarpPanel or some control else without columns too, look at this imaginary image:
notice that there is no rows and no columns. this is what i wanna make.
anybody have ideas to solve this issue?

You could write your own custom Panel class. There are some tutorials on the web, simply google "wpf custom panel".
It boils down to overriding the MeasureOverride and ArrangeOverride methods.
public class CustomPanel : Panel
{
protected override Size MeasureOverride(Size availableSize)
{
Size panelDesiredSize = new Size();
foreach (UIElement child in InternalChildren)
{
child.Measure(availableSize);
// Use child.DesiredSize, availableSize.Width and the positions
// and sizes of the previous children to calculate the position of
// the current child. Then determine the resulting Panel height.
panelDesiredSize = ...
}
return panelDesiredSize;
}
protected override Size ArrangeOverride(Size finalSize)
{
foreach (UIElement child in InternalChildren)
{
// Arrange each child according to the position calculations
// done in MeasureOverride
Point position = ...
child.Arrange(new Rect(position, child.DesiredSize));
}
return finalSize;
}
}
UPDATE: The following simple custom Panel might more or less do what you want.
public class PackPanel : Panel
{
protected override Size MeasureOverride(Size availableSize)
{
foreach (UIElement child in InternalChildren)
{
child.Measure(availableSize);
}
var positions = new Point[InternalChildren.Count];
var desiredHeight = ArrangeChildren(positions, availableSize.Width);
return new Size(availableSize.Width, desiredHeight);
}
protected override Size ArrangeOverride(Size finalSize)
{
var positions = new Point[InternalChildren.Count];
ArrangeChildren(positions, finalSize.Width);
for (int i = 0; i < InternalChildren.Count; i++)
{
var child = InternalChildren[i];
child.Arrange(new Rect(positions[i], child.DesiredSize));
}
return finalSize;
}
private double ArrangeChildren(Point[] positions, double availableWidth)
{
var lastRowStartIndex = -1;
var lastRowEndIndex = 0;
var currentWidth = 0d;
var desiredHeight = 0d;
for (int childIndex = 0; childIndex < InternalChildren.Count; childIndex++)
{
var child = InternalChildren[childIndex];
var x = 0d;
var y = 0d;
if (currentWidth == 0d || currentWidth + child.DesiredSize.Width <= availableWidth)
{
x = currentWidth;
currentWidth += child.DesiredSize.Width;
}
else
{
currentWidth = child.DesiredSize.Width;
lastRowStartIndex = lastRowEndIndex;
lastRowEndIndex = childIndex;
}
if (lastRowStartIndex >= 0)
{
int i = lastRowStartIndex;
while (i < lastRowEndIndex - 1 && positions[i + 1].X < x)
{
i++;
}
while (i < lastRowEndIndex && positions[i].X < x + child.DesiredSize.Width)
{
y = Math.Max(y, positions[i].Y + InternalChildren[i].DesiredSize.Height);
i++;
}
}
positions[childIndex] = new Point(x, y);
desiredHeight = Math.Max(desiredHeight, y + child.DesiredSize.Height);
}
return desiredHeight;
}
}

You Can Either use Canvas:
Or Use Grid and set the Margin of each Buttons according to requirenment
<Canvas >
<Button Content="s" Width="50" Canvas.Left="17" Canvas.Top="20" />
<Button Canvas.Left="73" Canvas.Top="32" Content="s" Width="60" Height="42" />
<Button Canvas.Left="139" Canvas.Top="10" Content="s" Height="42" Width="60" />
</Canvas>
<Grid >
<Button Content="01" Height="30" Width="70" Margin="20,12,414,268" />
<Button Content="02" Height="35" Width="72" Margin="426,148,6,128" />
<Button Content="03" Height="20" Width="74" Margin="190,122,240,170" />
<Button Content="04" Height="25" Width="76" Margin="386,26,40,260" />
<Button Content="05" Height="18" Width="78" Margin="376,202,48,92" />
<Button Content="06" Height="50" Width="70" Margin="385,64,48,196" />
<Button Content="07" Height="40" Width="72" Margin="162,202,269,68" />
<Button Content="08" Height="55" Width="74" Margin="20,154,408,102" />
<Button Content="09" Height="45" Width="76" Margin="21,95,406,171" />
<Button Content="10" Height="25" Width="78" Margin="44,47,382,239" />
<Button Content="11" Height="20" Width="80" Margin="386,120,38,170" />
<Button Content="12" Height="30" Width="70" Margin="95,13,338,268" />
<Button Content="13" Height="45" Width="72" Margin="290,6,140,260" />
<Button Content="14" Height="30" Width="74" Margin="210,38,220,244" />
<Button Content="15" Height="20" Width="76" Margin="128,48,299,242" />
<Button Content="16" Height="25" Width="78" Margin="265,189,160,97" />
<Button Content="17" Height="35" Width="80" Margin="176,154,246,122" />
<Button Content="18" Height="50" Width="70" Margin="100,146,333,116" />
<Button Content="19" Height="55" Width="72" Margin="270,121,160,135" />
<Button Content="20" Height="45" Width="74" Margin="348,148,81,118" />
<Button Content="21" Height="20" Width="76" Margin="94,78,332,212" />
<Button Content="22" Height="60" Width="78" Margin="270,60,155,192" />
<Button Content="23" Height="20" Width="80" Margin="176,74,247,216" />
<Button Content="24" Height="25" Width="70" Margin="194,95,238,191" />
<Button Content="25" Height="30" Width="72" Margin="117,104,314,177" />
</Grid>

Related

Button opacity doesn't work. How i can replace it

Program can't execute.
My XAML:
<ToolBar x:Name="toolBar1" DockPanel.Dock="Top" >
<Button x:Name="cut2" ToolTip="Cut" >
<Image Source="img/cut.png" Stretch="None" IsEnabledChanged="save2_IsEnabledChanged" />
</Button>
<Button x:Name="copy2" ToolTip="Copy" >
<Image Source="img/copy.png" Stretch="None" IsEnabledChanged="save2_IsEnabledChanged" />
</Button>
<Button x:Name="paste2" Command="ApplicationCommands.Paste" ToolTip="Paste" IsEnabledChanged="save2_IsEnabledChanged" >
<Image Source="img/paste.png" Stretch="None" />
</Button>
</ToolBar>
My cs:
private void save2_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
{
Button b = sender as Button;
b.Opacity = b.IsEnabled ? 1 : 0.5;
}
The problem in Opacity. It's just doesn't work.

Creation of controls dynamically on a separate thread

I am developing a WPF app, to generate folders dynamically
Right now I have an issue with what happens if the user puts 10000 folders? I am trying to run my for loop in another thread
By the way, how can I limit the user to create x number of folders?
Code Behind:
public MainWindowVM() {
SaveCommand = new Command(SaveAction);
FoldersCollection = new ObservableCollection<FolderData>();
CreateCommand = new Command(CreateAction);
CreateFoldersCommand = new Command(CreateFolderAction);
}
private void SaveAction() {
}
private void CreateFolderAction() {
var dirrName = "Assets";
var workingDirectory = Environment.CurrentDirectory;
// This will get the current PROJECT directory
var projectDirectories = Directory.GetParent(workingDirectory).Parent.Parent.GetDirectories(dirrName)
.ToList();
var path = Path.GetFullPath(projectDirectories.First().FullName);
foreach (var item in FoldersCollection) {
Directory.CreateDirectory($"{path}\\{item.FolderName}");
}
}
private void CreateAction() {
for (int i = 0; i < Value; i++) {
Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new ThreadStart(delegate {
FoldersCollection.Add(new FolderData() { FolderID = i, FolderName = string.Empty, Extenion = new List<string>() });
}));
XAML:
<WrapPanel>
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="600" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="110" />
<ColumnDefinition Width="400" />
</Grid.ColumnDefinitions>
<Label Content="Number of folders: " />
<TextBox
Grid.Column="1"
VerticalAlignment="Center"
PreviewTextInput="FolderNames_count"
Text="{Binding Value, UpdateSourceTrigger=PropertyChanged}" />
<Button
Grid.Column="1"
HorizontalAlignment="Right"
VerticalAlignment="Center"
BorderBrush="Transparent"
Command="{Binding CreateCommand}"
Content="Create"
Focusable="False" />
<ScrollViewer
Grid.Row="1"
Grid.ColumnSpan="2"
Margin="10"
BorderBrush="Transparent"
Focusable="False"
HorizontalScrollBarVisibility="Auto">
<ItemsControl ItemsSource="{Binding FoldersCollection}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock
Margin="0,10,0,0"
VerticalAlignment="Center"
FontStyle="Oblique"
Text="{Binding FolderID}" />
<syncfusion:SfTextBoxExt
Width="300"
Margin="10,10,0,0"
VerticalAlignment="Center"
Text="{Binding FolderName, UpdateSourceTrigger=PropertyChanged}"
Watermark="Folder Name" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
<Button
Grid.Row="2"
VerticalAlignment="Center"
Command="{Binding CreateFoldersCommand}"
Content="Create structure"
Style="{StaticResource MenuItem}" />
<Button
Grid.Row="2"
Grid.Column="1"
Margin="5,0,0,0"
VerticalAlignment="Center"
Command="{Binding SaveCommand}"
Content="Save structure"
Style="{StaticResource MenuItem}" />
</Grid>
</WrapPanel>
The app works fine, but when I exit, I get this error
btw I am doing this to allow numbers in my textbox
private void FolderNames_count(object sender, TextCompositionEventArgs e) {
if (!char.IsDigit(e.Text, e.Text.Length - 1))
e.Handled = true;
}
If you commands run on separate thread, then it looks like the bg thread still running during GUI thread is finished.
My recommendation is to put the handling of this case to the Window.Closing handler, i.e. do notify thread to break the loop, e.g. set cancellation token.
The brutal option would be to call Enviroment.Exit(0) method in the Window.Closing or Window.Closed handler, to terminate all threads. See Environment.Exit(Int32) Method
It's the loop should be executed on a background thread:
private void CreateAction()
{
Task.Run(() =>
{
for (int i = 0; i < Value; i++)
{
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
FoldersCollection.Add(new FolderData() { FolderID = i })));
}
});
}

Implementing Drag and Swapping items in windows Phone

I am new to windows phone.My problem is the following:
I have a grid of items which are buttons. I want to implement drag and swap feature for the buttons.How to do this in WP7 platform.
Here is the solution! xaml looks like this
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<toolkit:WrapPanel Height="510" HorizontalAlignment="Left" Margin="18,56,0,0" Name="wrapPanel1" VerticalAlignment="Top" Width="411">
<Button Content="1" Height="124" Name="button2" Width="134">
<toolkit:GestureService.GestureListener>
<toolkit:GestureListener DragDelta="GestureListener_DragDelta" DragStarted="GestureListener_DragStarted" DragCompleted="GestureListener_DragCompleted" />
</toolkit:GestureService.GestureListener>
</Button>
<Button Content="2" Height="124" Name="button3" Width="134" >
<toolkit:GestureService.GestureListener>
<toolkit:GestureListener DragDelta="GestureListener_DragDelta" DragStarted="GestureListener_DragStarted" DragCompleted="GestureListener_DragCompleted" />
</toolkit:GestureService.GestureListener>
</Button>
<Button Content="3" Height="124" Name="button4" Width="134">
<toolkit:GestureService.GestureListener>
<toolkit:GestureListener DragDelta="GestureListener_DragDelta" DragStarted="GestureListener_DragStarted" DragCompleted="GestureListener_DragCompleted" />
</toolkit:GestureService.GestureListener>
</Button>
<Button Content="4" Height="124" Name="button5" Width="134">
<toolkit:GestureService.GestureListener>
<toolkit:GestureListener DragDelta="GestureListener_DragDelta" DragStarted="GestureListener_DragStarted" DragCompleted="GestureListener_DragCompleted" />
</toolkit:GestureService.GestureListener>
</Button>
<Button Content="5" Height="124" Name="button6" Width="134">
<toolkit:GestureService.GestureListener>
<toolkit:GestureListener DragDelta="GestureListener_DragDelta" DragStarted="GestureListener_DragStarted" DragCompleted="GestureListener_DragCompleted" />
</toolkit:GestureService.GestureListener>
</Button>
<Button Content="6" Height="124" Name="button7" Width="134">
<toolkit:GestureService.GestureListener>
<toolkit:GestureListener DragDelta="GestureListener_DragDelta" DragStarted="GestureListener_DragStarted" DragCompleted="GestureListener_DragCompleted" />
</toolkit:GestureService.GestureListener>
</Button>
<Button Content="7" Height="124" Name="button8" Width="134">
<toolkit:GestureService.GestureListener>
<toolkit:GestureListener DragDelta="GestureListener_DragDelta" DragStarted="GestureListener_DragStarted" DragCompleted="GestureListener_DragCompleted" />
</toolkit:GestureService.GestureListener>
</Button>
<Button Content="8" Height="124" Name="button9" Width="134">
<toolkit:GestureService.GestureListener>
<toolkit:GestureListener DragDelta="GestureListener_DragDelta" DragStarted="GestureListener_DragStarted" DragCompleted="GestureListener_DragCompleted" />
</toolkit:GestureService.GestureListener>
</Button>
<Button Content="9" Height="124" Name="button10" Width="134">
<toolkit:GestureService.GestureListener>
<toolkit:GestureListener DragDelta="GestureListener_DragDelta" DragStarted="GestureListener_DragStarted" DragCompleted="GestureListener_DragCompleted" />
</toolkit:GestureService.GestureListener>
</Button>
<Button Content="10" Height="124" Name="button11" MouseLeftButtonDown="mouseDown" Width="134">
<toolkit:GestureService.GestureListener>
<toolkit:GestureListener DragDelta="GestureListener_DragDelta" DragStarted="GestureListener_DragStarted" DragCompleted="GestureListener_DragCompleted" />
</toolkit:GestureService.GestureListener>
</Button>
<Button Content="11" Height="124" Name="button12" Width="134">
<toolkit:GestureService.GestureListener>
<toolkit:GestureListener DragDelta="GestureListener_DragDelta" DragStarted="GestureListener_DragStarted" DragCompleted="GestureListener_DragCompleted" />
</toolkit:GestureService.GestureListener>
</Button>
<Button Content="12" Height="124" Name="button13" Width="134">
<toolkit:GestureService.GestureListener>
<toolkit:GestureListener DragDelta="GestureListener_DragDelta" DragStarted="GestureListener_DragStarted" DragCompleted="GestureListener_DragCompleted" />
</toolkit:GestureService.GestureListener>
</Button>
</toolkit:WrapPanel>
</Grid>
Now the code behind C#
TranslateTransform translateTransform;
PointCollection points = new System.Windows.Media.PointCollection();
Button firstObject;
private void GestureListener_DragStarted(object sender, DragStartedGestureEventArgs e)
{
translateTransform = new TranslateTransform();
firstObject = sender as Button;
var transform1 = firstObject.TransformToVisual(wrapPanel1);
Point absolutePosition1 = transform1.Transform(new Point(0, 0));
}
private void GestureListener_DragDelta(object sender, DragDeltaGestureEventArgs e)
{
var moveablebutton = sender as Button;
moveablebutton.RenderTransform = translateTransform;
translateTransform.X += e.HorizontalChange;
translateTransform.Y += e.VerticalChange;
}
private void GestureListener_DragCompleted(object sender, DragCompletedGestureEventArgs e)
{
var lastObject = sender as Button;
Button b=new Button();
int count = wrapPanel1.Children.Count;
int index = wrapPanel1.Children.IndexOf(lastObject);
var transform2 = lastObject.TransformToVisual(wrapPanel1);
Point absolutePositon2 = transform2.Transform(new Point(0, 0));
Point P1;
Point P2 ;
Point P3 ;
Point P4 ;
P1 = e.GetPosition(wrapPanel1);
P2 = new Point(P1.X+134, P1.Y+124);
Button swapitem=null;
foreach (UIElement ctrl in wrapPanel1.Children)
{
int index2;
var transform3 = ctrl.TransformToVisual(wrapPanel1);
Point comparePos = transform3.Transform(new Point(0, 0));
swapitem = ctrl as Button;
index2 = wrapPanel1.Children.IndexOf(swapitem);
if (index != index2)
{
P3 = new Point(comparePos.X, comparePos.Y);
P4 = new Point(comparePos.X + 158, comparePos.Y+170);
if (!(P2.Y < P3.Y || P1.Y > P4.Y || P2.X < P3.X || P1.X > P4.X))
{
swapitem = ctrl as Button;
index2 = wrapPanel1.Children.IndexOf(swapitem);
b = lastObject as Button;
b.RenderTransform = translateTransform;
translateTransform.X -= e.HorizontalChange;
translateTransform.Y -= e.VerticalChange;
wrapPanel1.Children.Remove(lastObject);
wrapPanel1.Children.Remove(swapitem);
// wrapPanel1.Children.RemoveAt(index2);
if (index < index2)
{
wrapPanel1.Children.Insert(index, swapitem);
wrapPanel1.Children.Insert(index2, b);
}
else
{
wrapPanel1.Children.Insert(index2, b);
wrapPanel1.Children.Insert(index, swapitem);
}
break;
}}
}
}

How can I make a control visible when WindowState is Maximized and collapsed when Normal?

This is my view, I want to collapse the second Rectange in the Button when windowstate is normal and vice versa. Mistakenly I changed the command name as ShowCommand, well I'm trying it but can't do it.
xaml:
<StackPanel>
<WrapPanel HorizontalAlignment="Center">
<Button Width="30" Height="20" Margin="0,30" Command="{Binding MinimizeCommand}" >
<Rectangle Width="8" Stroke="Black" StrokeThickness="2"/>
</Button>
<Button Width="30" Height="20" Command="{Binding ShowCommand}" >
<Grid >
<Rectangle Width="8" Height="8" Stroke="Black" StrokeThickness="2"
HorizontalAlignment="Right"
Margin="0,3,5,3" />
<Rectangle Visibility="{Binding MaximizeButtonVisibility}" Stroke="Black"
x:Name="RectMaxButton" Margin="10,0,0,8" Width="8" Height="8"
StrokeThickness="2" />
</Grid>
</Button>
<Button Width="30" Height="20" Margin="0,30" Command="{Binding ExitCommand}"
FontWeight="Bold">X</Button>
</WrapPanel>
</StackPanel>
cs:
public ICommand ShowCommand
{
get
{
if (_showCommand == null)
_showCommand = new RelayCommand(para => CanExit(), param => ToggleMaximizeWindwo());
return _showCommand;
}
}
public Visibility MaximizeButtonVisibility
{
get
{
this._maximizeButtonVisibility = Application.Current.MainWindow.WindowState == WindowState.Maximized ? Visibility.Visible : Visibility.Collapsed;
return this._maximizeButtonVisibility;
}
set
{
this._maximizeButtonVisibility = value;
base.OnPropertyChanged("MaximizeButtonVisility");
}
}
private void ToggleMaximizeWindwo()
{
if (Application.Current.MainWindow.WindowState == WindowState.Normal)
{
Application.Current.MainWindow.WindowState = WindowState.Maximized;
MaximizeButtonVisibility = Visibility.Visible;
}
else
{
Application.Current.MainWindow.WindowState = WindowState.Normal;
MaximizeButtonVisibility = Visibility.Collapsed;
}
}
It looks like you have a typo in your MaximizeButtonVisibility setter in the OnPropertyChanged. You have it as "MaximizeButtonVisility" when it should be "MaximizeButtonVisibility".
It might be helpful for someone, but if you were to consistently use
OnPropertyChanged(nameof(MaximizeButtonVisibility));
Then the name cannot be wrong, and this will also continue to work if the property is renamed.

UserControl with Exposable Command on WPF

I'm creating a Toolbar with some buttons, and I want each button to execute an different command according to the ViewModel attached to it's DataContext, so I created if like this:
public readonly DependencyProperty NewCommandProperty = DependencyProperty.Register(
"NewCommand", typeof(ICommand),
typeof(VirtueGridToolbar));
public ICommand NewCommand
{
get
{
return (ICommand)GetValue(NewCommandProperty);
}
set
{
SetValue(NewCommandProperty, value);
}
}
public GridToolbar()
{
InitializeComponent();
}
and the xaml of the control is this:
<UserControl x:Class="Virtue.Modules.Library.Controls.GridToolbar"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ToolBar Background="Transparent">
<ToolBar.Items>
<Button x:Name="NewButton"
Width="25"
Height="25"
ToolTip="Novo"
Command="{Binding NewCommand}">
<Image Source="{DynamicResource NewLarge}" />
</Button>
<Button x:Name="EditButton"
Width="25"
Height="25"
ToolTip="Editar">
<Image Source="{DynamicResource EditLarge}" />
</Button>
<Button x:Name="DeleteButton"
Width="25"
Height="25"
ToolTip="Excluir">
<Image Source="{DynamicResource DeleteLarge}" />
</Button>
<Separator />
<Button x:Name="SaveButton"
Width="25"
Height="25"
ToolTip="Excluir">
<Image Source="{DynamicResource SaveLarge}" />
</Button>
</ToolBar.Items>
</ToolBar>
</UserControl>
But when I add the UserControl to another control and attribute the Command
<V:GridToolbar NewCommand="{Binding Path=New}" />
the command does not execute.
Any suggestions?
Tks,
Diego

Resources