NullReferenceException in DragDrop after adding Items to ListBox - c#

I am trying to implement a dynamic ListBox that contains the "open files" of my program. Those files can be dragged from the ListBox into one of four Canvases.
That works all fine as long as the items are added in XAML before starting the program, however, once I add items to the ListBox via fileList.Items.Add("myitemname"); I get a NullReferenceException if I try to drop (dragging works) them into the Canvas at
DragDrop.DoDragDrop(listBox, dragData, DragDropEffects.Move);
Here the relevant part of my code:
public partial class MainWindow : Window
{
InitialDataObject _initData = new InitialDataObject();
public MainWindow()
{
InitializeComponent();
}
#region DragImage
private void DragImageStart(object sender, MouseButtonEventArgs e)
{
_initData._mousePoint = e.GetPosition(null);
}
private void DragImageMove(object sender, MouseEventArgs e)
{
Point mousePos = e.GetPosition(null);
Vector diff = _initData._mousePoint - mousePos;
if (e.LeftButton == MouseButtonState.Pressed && (
Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance ||
Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance) && ((sender as ListBox).SelectedItem != null))
{
var listBox = sender as ListBox;
var listBoxItem = listBox.SelectedItem;
DataObject dragData = new DataObject(_initData._dropIdentifier, listBoxItem);
DragDrop.DoDragDrop(listBox, dragData, DragDropEffects.Move);
}
}
private void CanvasDrop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(_initData._dropIdentifier))
{
var item = e.Data.GetData(_initData._dropIdentifier) as ListBoxItem;
(sender as Canvas).Background = new SolidColorBrush(Color.FromArgb(255, 255, 255, 255));
DropImage(sender as Canvas, item);
fileList.UnselectAll();
}
}
private void CanvasDragEnter(object sender, DragEventArgs e)
{
if (!e.Data.GetDataPresent(_initData._dropIdentifier) || sender == e.Source)
{
(sender as Canvas).Background = new SolidColorBrush(Color.FromArgb(255, 240, 240, 240));
e.Effects = DragDropEffects.None;
}
}
private void DropImage(Canvas targetCanvas, ListBoxItem item)
{
//just to check if I got the right item in this method
MessageBox.Show(item.Content.ToString());
}
private void CanvasDragLeave(object sender, DragEventArgs e)
{
if (!e.Data.GetDataPresent(_initData._dropIdentifier) || sender == e.Source)
{
(sender as Canvas).Background = new SolidColorBrush(Color.FromArgb(255, 255, 255, 255));
}
}
#endregion
private void sdfsdf(object sender, RoutedEventArgs e)
{
fileList.Items.Add("test");
}
}
class InitialDataObject
{
public Point _mousePoint = new Point();
public readonly string _dropIdentifier = "dropIdentifier";
}
XAML:
<Grid Height="Auto" HorizontalAlignment="Stretch" Margin="0,23,0,0" Name="gridSubmain" VerticalAlignment="Stretch" Width="Auto" Panel.ZIndex="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="250" MaxWidth="250" MinWidth="250" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ListBox Height="Auto" Name="fileList" Width="Auto" Background="#FFE6E6E6" BorderBrush="{x:Null}" Panel.ZIndex="1" PreviewMouseLeftButtonDown="DragImageStart" PreviewMouseMove="DragImageMove" FontSize="16" ItemsSource="{Binding}" Margin="0" Grid.Row="2">
<ListBoxItem Content="dfgdfg" />
<ListBoxItem Content="sfsdf" />
<ListBoxItem Content="ghjgh" />
<ListBoxItem Content="cvbcvb" />
</ListBox>
<Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="112,196,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="sdfsdf" />
</Grid>
<Grid Grid.Column="1" Height="Auto" HorizontalAlignment="Stretch" Margin="0" Name="gridImage" VerticalAlignment="Stretch" Width="Auto">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Canvas Height="Auto" HorizontalAlignment="Stretch" Margin="0" Name="canvasImage1" VerticalAlignment="Stretch" Width="Auto" AllowDrop="True" Drop="CanvasDrop" DragEnter="CanvasDragEnter" Background="White" DragLeave="CanvasDragLeave" />
<Canvas Height="Auto" HorizontalAlignment="Stretch" Margin="0" Name="canvasImage2" VerticalAlignment="Stretch" Width="Auto" Drop="CanvasDrop" DragEnter="CanvasDragEnter" Grid.Column="1" AllowDrop="True" Background="White" DragLeave="CanvasDragLeave"/>
<Canvas Height="Auto" HorizontalAlignment="Stretch" Margin="0" Name="canvasImage3" VerticalAlignment="Stretch" Width="Auto" Drop="CanvasDrop" DragEnter="CanvasDragEnter" Grid.Row="1" AllowDrop="True" Background="White" DragLeave="CanvasDragLeave"/>
<Canvas Height="Auto" HorizontalAlignment="Stretch" Margin="0" Name="canvasImage4" VerticalAlignment="Stretch" Width="Auto" Drop="CanvasDrop" DragEnter="CanvasDragEnter" Grid.Column="1" Grid.Row="1" AllowDrop="True" Background="White" DragLeave="CanvasDragLeave"/>
</Grid>
Any ideas why it is working with existing items but not with ones added via fileList.Items.Add("..");? Also, with existing Items the fileList.UnselectAll(); works fine, but the extra added items stay selected and I can't get rid of the selection.

Problem in you CanvasDrop method. You expect ListBoxItem there, but get string, because SelectedItem property of list box have different values for items you create in xaml and items you add dynamically.

Related

MessageBox in material design wpf c#

I’m using Material Design In XAML Toolkit C# ,MessageBox in material design WPF C# ,
I need like this or better Design for MessageBox 👌
I’ve tried use DialogHost but this Error happens
No loaded DialogHost instances.
private async void MenuPopupButton_OnClick(object sender, RoutedEventArgs e) {
var sampleMessageDialog = new SampleMessageDialog {
Message = {Text = "Goodbye"}
};
await DialogHost.Show(sampleMessageDialog, "RootDialog");
}
No loaded DialogHost instances.
I have developed one custom message box(using material design controls) in my application.
i'll show you the code below of WPF XAML and C#.
it contains three types of message boxes as below.
Yes,No
Ok
Ok,Cancel
Download code from below link.
https://github.com/sandeepjadhav75502/CustomMessageBoxWPF
WPF XAML Code
Heading
<Window x:Class="EVotingDashBoard.MessageBoxCustom"
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"
mc:Ignorable="d"
Title="MessageBoxWindow" Height="220" Width="500"
WindowStartupLocation="CenterScreen" WindowStyle="None" Background="White"
ResizeMode="CanResize" Topmost="True" ShowInTaskbar="False"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
TextElement.FontWeight="Regular"
TextElement.FontSize="10"
TextOptions.TextFormattingMode="Ideal"
TextOptions.TextRenderingMode="Auto"
FontFamily="{DynamicResource MaterialDesignFont}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="197*"/>
<ColumnDefinition Width="295*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<materialDesign:Card x:Name="cardHeader" Grid.Row="0" Padding="10" Margin="0" materialDesign:ShadowAssist.ShadowDepth="Depth5" Background="{DynamicResource PrimaryHueDarkBrush}" Foreground="{DynamicResource PrimaryHueDarkForegroundBrush}" Visibility="Visible" Grid.ColumnSpan="2">
<StackPanel>
<TextBlock x:Name="txtTitle" HorizontalAlignment="Center" VerticalAlignment="Stretch" Style="{DynamicResource MaterialDesignTitleTextBlock}" FontSize="20" >Message Title</TextBlock>
</StackPanel>
</materialDesign:Card>
<StackPanel HorizontalAlignment="Right" Margin="0,5,5,0" VerticalAlignment="Top" Grid.Column="1">
<Button x:Name="btnClose" Click="btnClose_Click" Width="35" Height="35" Background="White" Foreground="{DynamicResource PrimaryHueDarkBrush}" Style="{StaticResource MaterialDesignFloatingActionDarkButton}">
<materialDesign:PackIcon Kind="Close" />
</Button>
</StackPanel>
<Grid Grid.Row="1" Grid.ColumnSpan="2">
<Grid Margin="20">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<materialDesign:TransitioningContent>
<materialDesign:TransitioningContent.OpeningEffects >
<materialDesign:TransitionEffect Kind="FadeIn" />
<materialDesign:TransitionEffect Kind="SlideInFromBottom" />
</materialDesign:TransitioningContent.OpeningEffects>
<TextBox x:Name="txtMessage" HorizontalAlignment="Center" IsReadOnly="True" Grid.Row="0" Margin="5" materialDesign:HintAssist.Hint="" FontSize="18" Style="{StaticResource MaterialDesignFloatingHintTextBox}" />
</materialDesign:TransitioningContent>
</Grid>
<Grid Grid.Row="1" Margin="0,20,0,5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button x:Name="btnOk" Click="btnOk_Click" Grid.Column="1" Style="{StaticResource MaterialDesignRaisedButton}" Margin="5" Width="100" Content="OK" ToolTip="Ok"/>
<Button x:Name="btnCancel" Click="btnCancel_Click" Grid.Column="2" Style="{StaticResource MaterialDesignRaisedButton}" Margin="5" Width="100" Content="Cancel" ToolTip="Cancel"/>
<Button x:Name="btnYes" Click="btnYes_Click" Grid.Column="1" Style="{StaticResource MaterialDesignRaisedButton}" Margin="5" Width="100" Content="Yes" ToolTip="Yes"/>
<Button x:Name="btnNo" Click="btnNo_Click" Grid.Column="2" Style="{StaticResource MaterialDesignRaisedButton}" Margin="5" Width="100" Content="No" ToolTip="No"/>
</Grid>
</Grid>
</Grid>
</Grid>
</Window>
C# Code Behind
/// <summary>
/// Interaction logic for MessageBoxCustom.xaml
/// </summary>
public partial class MessageBoxCustom : Window
{
public MessageBoxCustom(string Message, MessageType Type, MessageButtons Buttons)
{
InitializeComponent();
txtMessage.Text = Message;
switch (Type)
{
case MessageType.Info:
txtTitle.Text = "Info";
break;
case MessageType.Confirmation:
txtTitle.Text = "Confirmation";
break;
case MessageType.Success:
{
txtTitle.Text = "Success";
}
break;
case MessageType.Warning:
txtTitle.Text = "Warning";
break;
case MessageType.Error:
{
txtTitle.Text = "Error";
}
break;
}
switch (Buttons)
{
case MessageButtons.OkCancel:
btnYes.Visibility = Visibility.Collapsed; btnNo.Visibility = Visibility.Collapsed;
break;
case MessageButtons.YesNo:
btnOk.Visibility = Visibility.Collapsed; btnCancel.Visibility = Visibility.Collapsed;
break;
case MessageButtons.Ok:
btnOk.Visibility = Visibility.Visible;
btnCancel.Visibility = Visibility.Collapsed;
btnYes.Visibility = Visibility.Collapsed; btnNo.Visibility = Visibility.Collapsed;
break;
}
}
private void btnYes_Click(object sender, RoutedEventArgs e)
{
this.DialogResult = true;
this.Close();
}
private void btnCancel_Click(object sender, RoutedEventArgs e)
{
this.DialogResult = false;
this.Close();
}
private void btnOk_Click(object sender, RoutedEventArgs e)
{
this.DialogResult = true;
this.Close();
}
private void btnNo_Click(object sender, RoutedEventArgs e)
{
this.DialogResult = false;
this.Close();
}
private void btnClose_Click(object sender, RoutedEventArgs e)
{
this.DialogResult = false;
this.Close();
}
}
public enum MessageType
{
Info,
Confirmation,
Success,
Warning,
Error,
}
public enum MessageButtons
{
OkCancel,
YesNo,
Ok,
}
we can call it like
private void Button_Close(object sender, RoutedEventArgs e)
{
bool? Result = new MessageBoxCustom("Are you sure, You want to close
application ?", MessageType.Confirmation, MessageButtons.YesNo).ShowDialog();
if (Result.Value)
{
Application.Current.Shutdown();
}
}
Consider using this package that has the following extra benefit features:
Custom styles for border window, message foreground and background, title foreground and background, border, etc
Button to copy message box details to clipboard
Scrollable message box content
Message content is .NET UIElement which can host any content

C# Combobox calling comboboxitem

I'm working on an Windows Application where you can block and allow programs. I have a problem on how to call the comboboxitem. inc is an item inside combobox 1 and all is an item inside combobox 2. I want to create a condition where if both comboboxitem are selected run this. How do i do that ? Thank you
private void addSubmitBtn_Click(object sender, RoutedEventArgs e)
{
foreach (string path in pathT.Text.Split(';'))
if (File.Exists(path))
{
if ( inc.SelectedIndex > -1 && all.SelectedIndex > -1)
{
FWRule(path, NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN, (blo.Checked) ? NET_FW_ACTION_.NET_FW_ACTION_BLOCK : NET_FW_ACTION_.NET_FW_ACTION_ALLOW, ((Control)sender).Tag.ToString());
}
if (outg.Checked || all.Checked)
{
FWRule(path, NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_OUT, (blo.Checked) ? NET_FW_ACTION_.NET_FW_ACTION_BLOCK : NET_FW_ACTION_.NET_FW_ACTION_ALLOW, ((Control)sender).Tag.ToString());
}
}
((System.Windows.Controls.Panel)this.Parent).Children.Remove(this);
}
private void FWRule(string path, NET_FW_RULE_DIRECTION_ d, NET_FW_ACTION_ fwaction, string action)
{
try
{
INetFwRule firewallRule = (INetFwRule)Activator.CreateInstance(
Type.GetTypeFromProgID("HNetCfg.FWRule"));
firewallRule.Action = fwaction;
firewallRule.Enabled = true;
firewallRule.InterfaceTypes = "All";
firewallRule.ApplicationName = path;
firewallRule.Name = "PRST: " + System.IO.Path.GetFileName(path);
INetFwPolicy2 firewallPolicy = (INetFwPolicy2)Activator.CreateInstance(Type.GetTypeFromProgID("HNetCfg.FwPolicy2"));
firewallRule.Direction = d;
if (action == "1") firewallPolicy.Rules.Add(firewallRule);
else
{
((System.Windows.Controls.Panel)this.Parent).Children.Remove(this);
}
}
catch (Exception ex) { System.Windows.Forms.MessageBox.Show(ex.Message, "ERROR"); }
}
private void addCancelBtn_Click(object sender, RoutedEventArgs e)
{
((System.Windows.Controls.Panel)this.Parent).Children.Remove(this);
}
private void addBackBtn_Click(object sender, RoutedEventArgs e)
{
((System.Windows.Controls.Panel)this.Parent).Children.Remove(this);
}
private void pathT_TextChanged(object sender, TextChangedEventArgs e)
{
}
private void blo_CheckedChanged(object sender, EventArgs e)
{
}
private void al_CheckedChanged(object sender, EventArgs e)
{
}
private void Button_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog fd = new OpenFileDialog();
fd.Filter = "Executable|*.exe";
fd.Multiselect = true;
if (fd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
pathT.Text = String.Join(";", fd.FileNames);
}
}
}
}
This is the XAML part
<UserControl x:Class="WpfDeepTest.Views.policyAddFunc"
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"
xmlns:md="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:local="clr-namespace:WpfDeepTest.Views"
mc:Ignorable="d"
d:DesignHeight="700" d:DesignWidth="960">
<Grid Background="{DynamicResource MaterialDesignPaper}">
<Grid.RowDefinitions>
<RowDefinition Height=".5*"/>
<RowDefinition Height="3*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height=".5*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="20 0 0 0">
<Button Name="addBackBtn" Style="{DynamicResource MaterialDesignFloatingActionButton}" Width="40" Height="40" Click="addBackBtn_Click">
<md:PackIcon Kind="ChevronLeft" Height="30" Width="30"/>
</Button>
</Grid>
<md:Card Grid.Row="1" Margin="15 10" Padding="100 0" Height="400">
<StackPanel VerticalAlignment="Center">
<Grid Margin="0 0 0 0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="1.5*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Application Path: " VerticalAlignment="Center" FontSize="25" Foreground="#616161" Padding="10 0 0 0"/>
<TextBox Name="pathT" Grid.Column="1" Background="#F5F5F5" VerticalContentAlignment="Center" FontSize="20" md:HintAssist.Hint="Ex: InboundPolicy#1" Padding="5 0" Margin="0,0,57.2,10.2" TextChanged="TextBox_TextChanged_1"/>
<Button Content="..." Grid.Column="1" HorizontalAlignment="Left" Margin="372,-1,0,0" VerticalAlignment="Top" Width="47" Height="36" Click="Button_Click"/>
</Grid>
<Grid Margin="0 30 0 0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="1.5*"/>
</Grid.ColumnDefinitions>
</Grid>
<Grid Margin="0 30 0 0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="280*"/>
<ColumnDefinition Width="138*"/>
<ColumnDefinition Width="13*"/>
<ColumnDefinition Width="31*"/>
<ColumnDefinition Width="66*"/>
<ColumnDefinition Width="171*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Directions: " VerticalAlignment="Center" FontSize="25" Foreground="#616161" Padding="10 0 0 0" Margin="0,-25,0,25"/>
<ComboBox x:Name="Combobox1" Grid.Column="1" Background="#F5F5F5" VerticalContentAlignment="Center" FontSize="20" Padding="5 0" Margin="0,-31,0.2,39" Grid.ColumnSpan="5">
<ComboBoxItem Name="all" Content="All" HorizontalAlignment="Left" Width="417.6"/>
<ComboBoxItem Name="inc" IsSelected="True" >OutBound</ComboBoxItem>
<ComboBoxItem Name="outg">InBound</ComboBoxItem>
</ComboBox>
</Grid>
<Grid Margin="0 30 0 0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="280*"/>
<ColumnDefinition Width="108*"/>
<ColumnDefinition Width="61*"/>
<ColumnDefinition Width="163*"/>
<ColumnDefinition Width="87*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Action: " VerticalAlignment="Center" FontSize="25" Foreground="#616161" Padding="10 0 0 0" Grid.ColumnSpan="2" Margin="2,-34,106,32.4"/>
<ComboBox x:Name="Combobox2" SelectedItem="" Grid.Column="1" Background="#F5F5F5" VerticalContentAlignment="Center" FontSize="20" Padding="5 0" Margin="2,-30,-1.8,36.4" Grid.ColumnSpan="4">
<ComboBoxItem Name="blo" IsSelected="True">Block</ComboBoxItem>
<ComboBoxItem Name="al">Allow</ComboBoxItem>
</ComboBox>
</Grid>
</StackPanel>
</md:Card>
<StackPanel Orientation="Horizontal" Grid.Row="2" HorizontalAlignment="Center">
<Button Name="addSubmitBtn" Style="{DynamicResource MaterialDesignRaisedButton}" VerticalAlignment="Top" Margin="10 20" Content="Submit" Width="150" Height="35" TabIndex="1" Click="addSubmitBtn_Click"/>
<Button Name="addCancelBtn" Style="{DynamicResource MaterialDesignRaisedLightButton}" VerticalAlignment="Top" Margin="10 20" Content="Cancel" Width="150" Height="35" Click="addCancelBtn_Click"/>
</StackPanel>
</Grid>
Here is a screenshot of the program
enter image description here
UPDATE
combobox items can be selected but not checked right? you should check if they are selected only. unless you build your own control that has a combobox of checkboxe items that can be checked
i think I found your problem, on your if condition, the situation can never happen because inc and all are part of <ComboBox x:Name="Combobox1", and in your code you are saying if ( inc.SelectedIndex > -1 && all.SelectedIndex > -1) those two can not be selected in the same time ;)
This for example should work because it has an OR operator if (outg.Checked || all.Checked), thous only one of those should be selected.
ignore below part, is a solution thinking that you were using Win Forms
you can use the selectedIndexChanged
like this for example:
private void comboBox2_SelectedIndexChanged(object sender, EventArgs e)
{
this.getValues(this.comboBox2, this.comboBox3);
}
private void comboBox3_SelectedIndexChanged(object sender, EventArgs e)
{
this.getValues(this.comboBox2, this.comboBox3);
}
public void compareValues(String value1, String value2)
{
if(value1.Equals("inc") && value2.Equals("all"))
{
this.runThis();
}
}
public void runThis()
{
//do your thing here :)
this.label1.Text = "run this!!!";
}
public void getValues(ComboBox cmb2, ComboBox cmb3)
{
String cmb1Value = "";
String cmb2Value = "";
try{
cmb1Value = this.comboBox2.SelectedItem.ToString();
}catch (Exception exception){
//not both set
}
try
{
cmb2Value = this.comboBox3.SelectedItem.ToString();
}catch (Exception exception){
//not both set
}
this.compareValues(cmb1Value, cmb2Value);
}
example of above code, running:

Grid Splitter working on diagonal?

I'm trying to do a Window with a transparent square inside it, and I want to allow the user to re-size it in whatever way s/he wants. This code is working for vertical and horizontal re-size
<Window x:Class="TransparentWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="PloofTAS" Height="355" Width="539" Topmost="True"
ResizeMode="NoResize"
AllowsTransparency="True"
Background="Transparent"
WindowStyle="None" MouseLeftButtonDown="Window_MouseLeftButtonDown">
<Grid Name="GlobalGrid">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="8" />
<RowDefinition Height="*" />
<RowDefinition Height="8" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="8" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="8" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Rectangle Fill="Gray" Grid.Column="0" Grid.RowSpan="5" />
<Rectangle Fill="Gray" Grid.Column="4" Grid.RowSpan="5" />
<Rectangle Fill="Gray" Grid.Column="1" Grid.Row="0" Grid.ColumnSpan="3" />
<Rectangle Fill="Gray" Grid.Column="1" Grid.Row="4" Grid.ColumnSpan="3" />
<GridSplitter Grid.Column="2" Grid.Row="1" Height="Auto" HorizontalAlignment="Stretch" />
<GridSplitter Grid.Column="1" Grid.Row="2" Height="Auto" HorizontalAlignment="Stretch" />
<GridSplitter Grid.Column="3" Grid.Row="2" Height="Auto" HorizontalAlignment="Stretch" />
<GridSplitter Grid.Column="2" Grid.Row="3" Height="Auto" HorizontalAlignment="Stretch" />
<Rectangle Fill="Orange" Grid.Row="1" Grid.Column="1" />
<Rectangle Fill="Orange" Grid.Row="1" Grid.Column="3" />
<Rectangle Fill="Orange" Grid.Row="3" Grid.Column="1" />
<Rectangle Fill="Orange" Grid.Row="3" Grid.Column="3" />
<Rectangle Fill="Transparent" Stroke="Red" Grid.Column="2" Grid.Row="2"/>
</Grid>
</Window>
Here is the resulting window
I'd like for the orange squares (the corners of the red/transparent square) to be able to work diagonally, or both vertical and horizontal. Is it possible?
I don't know elegant solution for this problem as GridSplitter is not possible to set up programmatically.
My solution is just dirty mouse capture and set Column and Row measures according to mouse movement.
Set style and events. Tag property store index of a row and column we gonna to change in code behind.
<Window.Resources>
<Style x:Key="DiagonalSplitterRectangle" TargetType="{x:Type Rectangle}">
<Setter Property="Fill" Value="Orange"/>
<EventSetter Event="MouseDown" Handler="UIElement_OnMouseDown"/>
<EventSetter Event="MouseMove" Handler="UIElement_OnMouseMove"/>
<EventSetter Event="MouseUp" Handler="UIElement_OnMouseUp"/>
<EventSetter Event="LostMouseCapture" Handler="UIElement_OnLostMouseCapture"/>
</Style>
</Window.Resources>
<Rectangle Grid.Row="1" Grid.Column="1" Style="{StaticResource DiagonalSplitterRectangle}" Tag="0,0"/>
<Rectangle Grid.Row="1" Grid.Column="3" Style="{StaticResource DiagonalSplitterRectangle}" Tag="0,4"/>
<Rectangle Grid.Row="3" Grid.Column="1" Style="{StaticResource DiagonalSplitterRectangle}" Tag="4,0"/>
<Rectangle Grid.Row="3" Grid.Column="3" Style="{StaticResource DiagonalSplitterRectangle}" Tag="4,4"/>
Simple mouse capture events:
private bool _isMouseCaptured;
public MainWindow()
{
InitializeComponent();
}
private void UIElement_OnMouseDown(object sender, MouseButtonEventArgs e)
{
var uiElement = sender as UIElement;
if (uiElement == null)
return;
if (uiElement.CaptureMouse())
_isMouseCaptured = true;
}
private void UIElement_OnMouseMove(object sender, MouseEventArgs e)
{
if (!_isMouseCaptured)
return;
var clientWindow = Content as FrameworkElement;
if (clientWindow == null)
return;
var rectangle = sender as Rectangle;
if (rectangle == null)
return;
Point position = Mouse.GetPosition(GlobalGrid); ;
if (position.X < 0 || position.Y < 0 || position.X > clientWindow.ActualWidth || position.Y > clientWindow.ActualHeight)
return;
GridUpdate(position, rectangle, clientWindow);
}
private void UIElement_OnMouseUp(object sender, MouseButtonEventArgs e)
{
if (!_isMouseCaptured)
return;
var uiElement = sender as UIElement;
if (uiElement == null)
return;
uiElement.ReleaseMouseCapture();
}
private void UIElement_OnLostMouseCapture(object sender, MouseEventArgs e)
{
_isMouseCaptured = false;
}
Resize grid columns and rows according to value stored in rectangle.Tag property.
For correct behavior was needed to change opposite column and row measures too.
private void GridUpdate(Point position, Rectangle rectangle, FrameworkElement clientWindow)
{
var gridPosition = new GridPosition(rectangle.Tag.ToString());
var oppositeGridPosition = GetOppositeGridPosition(gridPosition);
var rowHeight = GetMeasure(gridPosition.Row, position.Y, clientWindow.ActualHeight);
var columnWidth = GetMeasure(gridPosition.Column, position.X, clientWindow.ActualWidth);
var oppositeRowHeight = GlobalGrid.RowDefinitions[oppositeGridPosition.Row].ActualHeight;
var oppositeColumnWidth = GlobalGrid.ColumnDefinitions[oppositeGridPosition.Column].ActualWidth;
GlobalGrid.RowDefinitions[gridPosition.Row].Height = new GridLength(rowHeight);
GlobalGrid.ColumnDefinitions[gridPosition.Column].Width = new GridLength(columnWidth);
GlobalGrid.RowDefinitions[oppositeGridPosition.Row].Height = new GridLength(oppositeRowHeight);
GlobalGrid.ColumnDefinitions[oppositeGridPosition.Column].Width = new GridLength(oppositeColumnWidth);
}
private GridPosition GetOppositeGridPosition(GridPosition gridPosition)
{
var row = (gridPosition.Row == 0) ? 4 : 0;
var column = (gridPosition.Column == 0) ? 4 : 0;
return new GridPosition(row, column);
}
private double GetMeasure(int gridPosition, double position, double windowMeasure)
{
return gridPosition == 0 ? position : windowMeasure - position;
}
GridPosition is structure that stores column and row index values.
public struct GridPosition
{
public int Row { get; private set; }
public int Column { get; private set; }
public GridPosition(int row, int column)
: this()
{
Row = row;
Column = column;
}
public GridPosition(string gridPostion)
: this()
{
Row = Convert.ToInt32(gridPostion.Split(',')[0]);
Column = Convert.ToInt32(gridPostion.Split(',')[1]);
}
}

how to remove dynamically created Row in user control in WPF?

I have created an User control. I am creating dynamically this user control in a Page. I have a button in that control to remove the row which is created dynamically. I am unable to remove the entire Row.
This is my Xaml:
<Grid Name="grid_usercontrolTypeofFixture" >
<Grid.RowDefinitions >
<RowDefinition Height="20*"/>
<RowDefinition Height="35*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="35*" />
<ColumnDefinition Width="50*" />
<ColumnDefinition Width="15*" />
<ColumnDefinition Width="10*" />
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Margin="10,5,5,5" Content="Select/Type Fixture Type:" />
<TextBox Grid.Row="0" Grid.Column="1" Margin="10,5,5,5" Text="" Name="txtAuto"/>
<TextBox Grid.Row="0" Grid.Column="2" Margin="10,5,5,5" Text="" Name="txt_percentage"/>
<Button Grid.Row="0" Grid.Column="3" Margin="10,5,5,5" x:Name="btn_removeRow" Content="" Click="btn_removeRow_Click">
<Button.Background>
<ImageBrush ImageSource="/Assets/Knob Cancel.png"></ImageBrush>
</Button.Background>
</Button>
</Grid>
This is My Code Behind:
public int count = 1;
private void btn_addnew_Click(object sender, RoutedEventArgs e)
{
var myControl = new UserControlTypeofFixture() { Name = "TypeofFixture" };
grid_typeFixture.RowDefinitions.Add(new RowDefinition());
Grid.SetRow(myControl, count);
grid_typeFixture.Margin = new Thickness(10, 10, 10, 10);
grid_typeFixture.Children.Add(myControl);
count++;
}
private void btn_removeRow_Click(object sender, RoutedEventArgs e)
{
???
}
I have some other code to remove the selected row. but its not working. How can i remove entire row?
This is how you can remove your usercontrol and rowdefinition
private void btn_removeRow_Click(object sender, RoutedEventArgs e)
{
var myControl = sender as Button;
int rowindex = (int)myControl.GetValue(Grid.RowProperty);
foreach (UIElement control in grid_typeFixture.Children)
{
var usercontrol = control as UserControlTypeofFixture;
if (usercontrol != null)
{
int childrowindex = (int)usercontrol.GetValue(Grid.RowProperty);
if (childrowindex == rowindex)
{
grid_typeFixture.Children.Remove(control);
grid_typeFixture.RowDefinitions.RemoveAt(childrowindex);
break;
}
}
}
}
Ok, then try the alternative solution I've mentioned, i.e. set the particular RowDefinition Height to 0: pertinent to your case it should be like the following:
private void btn_removeRow_Click(object sender, RoutedEventArgs e)
{
grid_typeFixture.RowDefinitions[2].Height = new GridLength(0);
}

Drag item from Listbox and start method on drop into specific Canvas

I am quite new to C# so please keep things as simple as possible.
My problem is as follows: I have a Listbox to which I add Items dynamically at runtime and I also have four different Canvases within my UI.
Now the user has to be able to drag any Item from the Listbox and drop it into one of the four Canvases.
Upon drop a method will be started which needs to know which Item has been draged and into which Canvas it was dropped.
I have not implemented anything yet but here at least my XAML:
<Grid Height="Auto" HorizontalAlignment="Stretch" Margin="0" Name="gridMenu" VerticalAlignment="Stretch" Width="Auto" Background="#FFE6E6E6">
<ListBox Grid.Row="2" Height="Auto" HorizontalAlignment="Stretch" Margin="0" Name="listBox1" VerticalAlignment="Stretch" Width="Auto" Background="#FFE6E6E6" BorderBrush="{x:Null}" Panel.ZIndex="1" PreviewMouseDown="listBox1_PreviewMouseLeftButtonDown">
<ListBoxItem Content="test1" />
<ListBoxItem Content="test2" />
<ListBoxItem Content="test3" />
<ListBoxItem Content="test4" />
<ListBoxItem Content="test5" />
</ListBox>
</Grid>
<Grid Grid.Column="1" Height="Auto" HorizontalAlignment="Stretch" Margin="0" Name="gridImage" VerticalAlignment="Stretch" Width="Auto" TextBlock.Drop="grid1_Drop">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Canvas Height="Auto" HorizontalAlignment="Stretch" Margin="0" Name="canvasImage1" VerticalAlignment="Stretch" Width="Auto" />
<Canvas Height="Auto" HorizontalAlignment="Stretch" Margin="0" Name="canvasImage2" VerticalAlignment="Stretch" Width="Auto" Grid.Column="1" />
<Canvas Height="Auto" HorizontalAlignment="Stretch" Margin="0" Name="canvasImage3" VerticalAlignment="Stretch" Width="Auto" Grid.Row="1" />
<Canvas Height="Auto" HorizontalAlignment="Stretch" Margin="0" Name="canvasImage4" VerticalAlignment="Stretch" Width="Auto" Grid.Column="1" Grid.Row="1" />
</Grid>
I think Drag and Drop isn't an easy topic, so I am afraid I can't make it that simple and I agree with ekholm: You will definitely need a decent c#/wpf knowledge to succesfully implement this. Even when you get your code to run you will be stuck when you want to modify/extend your DragDrop Code.
Here's an example to get you started based on your provided markup:
XAML:
<Grid Grid.Row="1" Height="Auto" HorizontalAlignment="Stretch" Margin="0" Name="gridImage" VerticalAlignment="Stretch" Width="Auto">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Canvas Background="LightGreen" AllowDrop="True" Drop="canvasImage_Drop" DragEnter="canvasImage_DragEnter" Height="Auto" HorizontalAlignment="Stretch" Margin="0" Name="canvasImage1" VerticalAlignment="Stretch" Width="Auto" />
<Canvas Background="LightYellow" AllowDrop="True" Drop="canvasImage_Drop" DragEnter="canvasImage_DragEnter" Height="Auto" HorizontalAlignment="Stretch" Margin="0" Name="canvasImage2" VerticalAlignment="Stretch" Width="Auto" Grid.Column="1" />
<Canvas Background="LightPink" AllowDrop="True" Drop="canvasImage_Drop" DragEnter="canvasImage_DragEnter" Height="Auto" HorizontalAlignment="Stretch" Margin="0" Name="canvasImage3" VerticalAlignment="Stretch" Width="Auto" Grid.Row="1" />
<Canvas Background="LightSteelBlue" AllowDrop="True" Drop="canvasImage_Drop" DragEnter="canvasImage_DragEnter" Height="Auto" HorizontalAlignment="Stretch" Margin="0" Name="canvasImage4" VerticalAlignment="Stretch" Width="Auto" Grid.Column="1" Grid.Row="1" />
</Grid>
</Grid>
Code behind:
private Point _startPoint;
private static readonly string _dropIdentifier = "dropIdentifier";
private void listBox_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
// The initial mouse position
_startPoint = e.GetPosition(null);
}
private void listBox_PreviewMouseMove(object sender, MouseEventArgs e)
{
// Get the current mouse position
Point mousePos = e.GetPosition(null);
Vector diff = _startPoint - mousePos;
if (e.LeftButton == MouseButtonState.Pressed &&
(Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance ||
Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance))
{
// Get the dragged ListBoxItem
var listBox = sender as ListBox;
var listBoxItem = listBox.SelectedItem;
// Initialize the drag & drop operation
DataObject dragData = new DataObject(_dropIdentifier, listBoxItem);
DragDrop.DoDragDrop(listBox, dragData, DragDropEffects.Move);
}
}
private void canvasImage_Drop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(_dropIdentifier))
{
var item = e.Data.GetData(_dropIdentifier) as ListBoxItem;
DropOnCanvas(sender as Canvas, item);
}
}
private void canvasImage_DragEnter(object sender, DragEventArgs e)
{
if (!e.Data.GetDataPresent(_dropIdentifier) ||
sender == e.Source)
{
e.Effects = DragDropEffects.None;
}
}
public void DropOnCanvas(Canvas targetCanvas, ListBoxItem item)
{
// do your stuff here ...
int textHeight = 20;
var text = new TextBlock() { Text = item.Content.ToString(), Height = textHeight };
Canvas.SetTop(text, targetCanvas.Children.Count * textHeight);
targetCanvas.Children.Add(text);
}
This tutorial should get you started: http://wpftutorial.net/DragAndDrop.html

Categories