Winforms: Controls not visible after added programmatically - winforms

I want to create a simple FileExplorer Control for a video player.
Here is the code:
namespace CustomControls
{
public interface IScrollable
{
float visiblePercent { get; set; }
float ScrollSpeedMultiplier { get; set; }
int scrollValue { get; set; }
CustomScrollBar scrollBar { get; set; }
}
}
namespace CustomControls {
public partial class ScrollablePanel : UserControl, IScrollable {
private int _scrollValue;
private int _totalWheelDelta;
private int totalWheelDelta {
get => _totalWheelDelta;
set {
SetTotalDelta(value);
}
}
public int Count => panelInner.Controls.Count;
public bool VisibleControls => panelInner.Controls.OfType<Panel>().All(p => p.Visible);
public float visiblePercent { get; set; }
public int scrollValue {
get { return _scrollValue; }
set {
_scrollValue = value;
if (scrollBar != null && scrollBar.value != _scrollValue)
scrollBar.value = _scrollValue;
SetTotalDeltaByScrollValue(value);
ScrollThrough();
}
}
[EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DefaultValue(0), Category("Behavior"), Description("Die dazugehörige Scrollbar")]
public CustomScrollBar scrollBar { get; set; }
public float ScrollSpeedMultiplier { get; set; }
public ScrollablePanel() {
InitializeComponent();
panelInner.MouseWheel += panelInner_MouseWheel;
}
protected override ControlCollection CreateControlsInstance() {
return new ScrollablePanelElementCollection(this, this.panelInner);
}
private void ScrollablePanel_Load(object sender, EventArgs e) {
OnControlsChanged();
}
private void panelInner_MouseWheel(object sender, MouseEventArgs e) {
if (visiblePercent >= 1.0f)
return;
totalWheelDelta += (int)(e.Delta * ScrollSpeedMultiplier);
scrollValue = (100 * SystemInformation.MouseWheelScrollLines * totalWheelDelta) / ((Height - panelInner.Height) * SystemData.scrollDeltaModifier);
if (scrollBar != null)
scrollValue = scrollBar.value = (100 * SystemInformation.MouseWheelScrollLines * totalWheelDelta) / ((Height - panelInner.Height) * SystemData.scrollDeltaModifier);
}
private void ScrollThrough() {
panelInner.Location = new Point(0, (int)((Height - panelInner.Height) * (scrollValue / 100.0f)));
}
private void panelInner_ControlAdded(object sender, ControlEventArgs e) {
OnControlsChanged();
}
private void panelInner_ControlRemoved(object sender, ControlEventArgs e) {
OnControlsChanged();
}
private void OnControlsChanged() {
int height = int.MinValue;
foreach (Control control in panelInner.Controls)
if (control.Visible)
height = Math.Max(height, control.Bottom);
panelInner.Height = height;
ScrollablePanel_Resize(this, new EventArgs());
if (panelInner.Height > 0)
visiblePercent = (float)Height / panelInner.Height;
else
visiblePercent = 1.0f;
if (scrollBar != null)
scrollBar.largeChange = (int)(visiblePercent * 100);
}
private void ScrollablePanel_Resize(object sender, EventArgs e) {
panelInner.Width = Width;
}
private void SetTotalDelta(int value) {
int lines = SystemInformation.MouseWheelScrollLines * (value / SystemData.scrollDeltaModifier);
int deltaHeight = Height - panelInner.Height;
if (lines > 0)
_totalWheelDelta = 0;
else if (lines < deltaHeight)
_totalWheelDelta = (deltaHeight * SystemData.scrollDeltaModifier) / SystemInformation.MouseWheelScrollLines;
else
_totalWheelDelta = value;
}
private void SetTotalDeltaByScrollValue(int value) {
int deltaHeight = Height - panelInner.Height;
totalWheelDelta = (deltaHeight * SystemData.scrollDeltaModifier * scrollValue) / (100 * SystemInformation.MouseWheelScrollLines);
}
public void Clear() {
panelInner.Controls.Clear();
}
}
public class ScrollablePanelElementCollection : Control.ControlCollection {
private Control container;
public ScrollablePanelElementCollection(Control owner, Panel container) : base(owner) { this.container = container; }
public override void Add(Control value) {
if (this.Count == 0)
base.Add(value);
else
container.Controls.Add(value);
}
}
}
namespace MagererPlayer {
public partial class FileExplorer : UserControl, IScrollable {
private string _directory;
public float visiblePercent {
get => scrollablePanel.visiblePercent;
set => scrollablePanel.visiblePercent = value;
}
public int scrollValue {
get => scrollablePanel.scrollValue;
set => scrollablePanel.scrollValue = value;
}
public CustomScrollBar scrollBar {
get => scrollablePanel.scrollBar;
set => scrollablePanel.scrollBar = value;
}
public string Directory {
get => this._directory;
set {
if (System.IO.Directory.Exists(value)) {
this._directory = value;
GetDirectory();
}
}
}
public float ScrollSpeedMultiplier { get; set; }
public EventHandler OnDirectoryChanged = null;
public EventHandler<FileSelectedEventArgs> OnFileSelected = null;
public FileExplorer() {
InitializeComponent();
}
private void FileExplorer_Load(object sender, EventArgs e) {
AdjustSize();
}
private void FileExplorer_Resize(object sender, EventArgs e) {
AdjustSize();
}
private void AdjustSize() {
}
private void GetDirectory() {
scrollablePanel.Clear();
System.Diagnostics.Trace.WriteLine(this.Directory);
int offset = System.IO.Directory.GetParent(this.Directory) != null ? 1 : 0;
int colCount = scrollablePanel.Width / 145;
string[] dirs = System.IO.Directory.GetDirectories(new string(this.Directory.Where(c => !char.IsControl(c)).ToArray()));
Array.Sort(dirs);
if (offset == 1) {
DirectoryInfo parent = System.IO.Directory.GetParent(this.Directory);
scrollablePanel.Controls.Add(GetExplorerItem(parent.FullName, "..", new Point(0, 0)));
}
for (int i = 0; i < dirs.Length; i++)
scrollablePanel.Controls.Add(GetExplorerItem(dirs[i], new DirectoryInfo(dirs[i]).Name, new Point(((i + offset) % colCount) * 145, (i + offset) / colCount * 115 + 10)));
offset += dirs.Length;
dirs = System.IO.Directory.GetFiles(new string(this.Directory.Where(c => !char.IsControl(c)).ToArray()), "*.mp4", SearchOption.TopDirectoryOnly);
Array.Sort(dirs);
for (int i = 0; i < dirs.Length; i++)
scrollablePanel.Controls.Add(GetExplorerItem(dirs[i], new FileInfo(dirs[i]).Name, new Point(((i + offset) % colCount) * 145, (i + offset) / colCount * 115 + 10)));
System.Diagnostics.Trace.WriteLine(scrollablePanel.Count);
System.Diagnostics.Trace.WriteLine(scrollablePanel.VisibleControls);
this.Invalidate();
}
private Panel GetExplorerItem(string path, string text, Point location) {
BunifuImageButton bunifuImageButton = new BunifuImageButton();
Label label = new Label();
Panel panel = new Panel();
if (System.IO.Directory.Exists(path)) {
bunifuImageButton.Image = Properties.Resources.folder;
bunifuImageButton.Click += delegate (object sender, EventArgs e) {
this.Directory = path;
};
} else if (System.IO.File.Exists(path)) {
bunifuImageButton.Image = Properties.Resources.video_1;
}
bunifuImageButton.ImageActive = null;
bunifuImageButton.Location = new System.Drawing.Point(10, 0);
bunifuImageButton.Name = "bunifuImageButton";
bunifuImageButton.Size = new System.Drawing.Size(125, 70);
bunifuImageButton.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
bunifuImageButton.TabStop = false;
bunifuImageButton.Zoom = 5;
bunifuImageButton.Cursor = Cursors.Hand;
label.Font = new System.Drawing.Font("Century Gothic", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 0);
label.ForeColor = System.Drawing.Color.FromArgb(224, 224, 224);
label.Name = "label";
label.Dock = DockStyle.Bottom;
label.Size = new Size(145, 40);
label.Text = text;
label.TextAlign = ContentAlignment.MiddleCenter;
label.AutoEllipsis = true;
panel.Controls.Add(bunifuImageButton);
panel.Controls.Add(label);
panel.Location = location;
panel.Name = "panel";
panel.Size = new System.Drawing.Size(145, 110);
return panel;
}
private void textBoxUrl_KeyDown(object sender, KeyEventArgs e) {
if (e.KeyCode == Keys.Enter) {
this.Directory = this.textBoxUrl.Text;
this.textBoxUrl.Text = this.Directory;
}
}
}
public class FileSelectedEventArgs : EventArgs {
public FileInfo File { get; }
public FileSelectedEventArgs(string path) {
File = new FileInfo(path);
}
public FileSelectedEventArgs(FileInfo info) {
File = info;
}
}
}
The Scrollable panel contains an inner panel that gets moved up and down. The FileExplorer contains a textbox for the URL, a button, and a scrollable panel.
My problem is that when I run the application everything works fine. When I go to the parent folder (IMPORTANT, NOT A SUBDIR) and reenter the folder all controls that should be there are invisible, but they were added to the inner panel's control collection.
This is the only folder dir where this error occurs: D:\Serien\Anime\Yu-Gi-Oh! Zexal
Output of System.Diagnostics from FileExplorer.GetDirectory:
D:\Serien\Anime\Yu-Gi-Oh! Zexal
3
True
D:\Serien\Anime
47
True
D:\Serien\Anime\Yu-Gi-Oh! Zexal
3
True
Screenshot of app start:
Screenshot after reenter:

Related

C# Windows.Forms.Timer doesnt work properly

I have some troubles while making simple application on C# / Windows.Forms that simulates a pendulum.
It's a simple application with all backend logic in form code.
First of all, I set up the interval equals 100 milliseconds (line 60), but when I calculate number of turns (line 155) and display it, displaying message:
refresh every second (not every 100 milliseconds)
and it behaves like this: 1-2-4-5-6-8 or 1-3-4-5-7-8 etc.
I don't know when it started bugging and want to determine the mistake.
Thanks a lot for your help.
using System;
using System.Drawing;
using System.Windows.Forms;
namespace Koban_Lab1
{
public partial class mainWindow : Form
{
public Point pendFulcrum = new Point(150, 0);
public Point pendTip = new Point();
private bool deviceState_;
private long ticks_;
private DateTime startTiming;
private Pen blackPencil;
public static double g = 9.8;
public double T;
public double periodInTicks;
public double L;
public double a;
public double Amp;
public double startOffset;
public double w;
public double periodCounter;
public double x;
public double y;
public double currentAngle;
private Timer timer_;
public double t;
public Bitmap field;
private long cnt = 0;
private bool DeviceState
{
get
{
return deviceState_;
}
set
{
if (value == deviceState_)
{
return;
}
deviceState_ = value;
switch (value)
{
case true:
L = Convert.ToDouble(pendulumLengthTextBox.Text) / 100;
a = Convert.ToDouble(plummetDistanceTextBox.Text) / 100;
periodCounter = 0;
T = 2 * Math.PI * Math.Sqrt((L * L) / (12 * g * a) + a / g);
w = 2 * Math.PI / T;
Amp = 2 * Math.PI * L / 24;
startOffset = Amp;
startTiming = DateTime.Now;
timer_ = new Timer();
timer_.Interval = 100;
timer_.Tick += new EventHandler(tickTimer);
timer_.Start();
startPendulumButton.Enabled = false;
stopPendulumButton.Enabled = true;
pendulumLengthTextBox.Enabled = false;
plummetDistanceTextBox.Enabled = false;
addReadoutButton.Enabled = true;
break;
case false:
timer_.Stop();
timer_ = null;
startPendulumButton.Enabled = true;
stopPendulumButton.Enabled = false;
pendulumLengthTextBox.Enabled = true;
plummetDistanceTextBox.Enabled = true;
timerTextBox1.Text = Locale.timerDisabledMessage;
timerTextBox2.Text = "0";
addReadoutButton.Enabled = false;
break;
}
return;
}
}
public Graphics fieldGraphics;
public mainWindow()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
pendulumLengthTooltip.SetToolTip(pendulumLengthTextBox, Locale.pendulumLengthTooltipMessage);
plummetDistanceTooltip.SetToolTip(plummetDistanceTextBox, Locale.plummetDistanceTooltipMessage);
blackPencil = Pens.Gray;
timerTextBox1.Text = Locale.timerDisabledMessage;
timerTextBox2.Text = "0";
deleteReadoutButton.Enabled = false;
DeviceState = false;
field = new Bitmap(pendulumField.Width, pendulumField.Height);
}
private void startPendulumButton_Click(object sender, EventArgs e)
{
DeviceState = true;
}
private void stopPendulumButton_Click(object sender, EventArgs e)
{
DeviceState = false;
}
private void addReadoutButton_Click(object sender, EventArgs e)
{
if (timerTextBox1.Text == Locale.timerDisabledMessage)
{
return;
}
readoutList.Items.Add(timerTextBox1.Text);
deleteReadoutButton.Enabled = true;
return;
}
private void deleteReadoutButton_Click(object sender, EventArgs e)
{
if (readoutList.SelectedIndex != (-1))
{
readoutList.Items.RemoveAt(readoutList.SelectedIndex);
}
else
{
readoutList.Items.RemoveAt(readoutList.Items.Count - 1);
}
if (readoutList.Items.Count == 0)
{
deleteReadoutButton.Enabled = false;
}
}
private void tickTimer(object sender, EventArgs e)
{
ticks_ = DateTime.Now.Ticks - startTiming.Ticks;
timerTextBox1.Text = TimeSpan.FromTicks(ticks_).ToString(#"mm\:ss\:ff");
timerTextBox2.Text = periodCounter.ToString();
ticks_ = DateTime.Now.Ticks - startTiming.Ticks;
t = ticks_ / TimeSpan.TicksPerSecond;
periodCounter = t / T;
timerTextBox2.Text = Convert.ToInt32(periodCounter).ToString();
currentAngle = Amp * Math.Sin(w * t);
x = x * Math.Cos(currentAngle) - y * Math.Sin(currentAngle);
y = x * Math.Sin(currentAngle) + y * Math.Cos(currentAngle);
Program.labWindow.fieldGraphics = Graphics.FromHwnd(Program.labWindow.pendulumField.Handle);
pendTip.X = (int)x;
pendTip.Y = (int)y;
fieldGraphics.DrawLine(blackPencil, pendFulcrum, pendTip);
pendulumField.Image = field;
Application.DoEvents();
}
private void plummetDistanceTooltip_Popup(object sender, PopupEventArgs e)
{
}
private void plummetDistanceLabel_Click(object sender, EventArgs e)
{
}
}
}

Handling events across different classes using C#

I have a property defined in Class A. When the property is changed then i need to raise an event. Another class B should respond to this event and do something. I have done something like this:
Code:
Class A{
string variable = "test";
public delegate void EventHandler(object sender, EventArgs args);
public static event EventHandler ThrowAddEvent = delegate { };
public static event EventHandler ThrowRemoveEvent = delegate { };
public String Name { get; set; }
public int Select { get; set; }
public Window Formref1 { get; set; }
public bool IsSelected
{
get { return IsSlctd; }
set
{
IsSlctd = value;
if (value)
{
ThrowAddEvent(this, new EventArgs());
}
else
{
ThrowRemoveEvent(this, new EventArgs());
}
}
}
}
Another class which is responding to this event is defined as follows:
Class B{
public B(ParsedResult _result)
{
InitializeComponent();
if (_result != null)
{
this.Result = _result;
PopulateColumns1();
DataGrid1.Items.Clear();
DataGrid1.ItemsSource = Populatevariables();
}
}
public void PopulateColumns1()
{
DataGridTextColumn Colvar = new DataGridTextColumn();
Colvar.Header = "Variables";
Colvar.Binding = new Binding("Name");
DataGrid1.Columns.Add(Colvar);
DataGridTemplateColumn Col = new DataGridTemplateColumn();
Col.Header = "Select";
DataTemplate dd = new DataTemplate();
FrameworkElementFactory FF = new FrameworkElementFactory(typeof(CheckBox));
FF.SetBinding(CheckBox.BindingGroupProperty, new Binding("Select"));
FF.SetBinding(CheckBox.IsCheckedProperty, new Binding("IsSelected") { UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged });
FF.SetValue(FrameworkElement.HorizontalAlignmentProperty, HorizontalAlignment.Center);
dd.VisualTree = FF;
Col.CellTemplate = dd;
DataGrid1.Columns.Add(Col);
}
private List<A> PopulateVariables()
{
CheckBox cb = new CheckBox();
List<A> CharList = new List<A>();
Result.GetCharacteristicList.MoveNext();
IEnumerator<A2LCharacteristic> enumeratorlist = Result.GetCharacteristicList;
for (int i = 0; enumeratorlist.MoveNext(); i++)
{
CharList.Add(new A() { Name = enumeratorlist.Current.Name, Select = i, Formref1 = this});
}
enumeratorlist.Reset();
return CharList;
}
private void OKBtn_Click(object sender, RoutedEventArgs e)
{
A Instance_A = new A();
Instance_A.ThrowAddEvent += (sender1, args) => { Addvrbl(Instance_A.variable); };
Instance_A.ThrowRemoveEvent += (sender2, args) => { RmvVrbl(Instance_A.variable); };
this.Close();
}
public void Addvrbl(string vrbl)
{
if (!(vrbllist.Contains(vrbl)))
{
vrbllist.Add(vrbl);
}
}
public void RmvVrbl(string vrbl)
{
if ((vrbllist.Contains(vrbl)))
{
vrbllist.Remove(vrbl);
}
}
}
The problem is it is not going inside the method "AddVrbl" and "RmvVrbl". I have used the solution from here. Please help.
OK, instead of subscribing to the event of a new instance of A,which will never get triggered/published. When you initializing CharList, you have to subscribe to the event of each A item.
Something like:
for (int i = 0; enumeratorlist.MoveNext(); i++)
{
var obja=new A() { Name = enumeratorlist.Current.Name, Select = i, Formref1 = this};
obja.ThrowAddEvent += ...
obja.ThrowRemoveEvent += ...
CharList.Add(obja);
}
PS: Make sure you un-subscribe these events before removing an item from your CharList.

Making a AnimationQueue

I have been trying to make a Ellipse to follow a given trajectory with the DoubleAnimation class. So far not too good.
I made a custom class AnimationQueue :
private class AnimationQueue
{
private List<DoubleAnimation> animation1 ;
private DependencyProperty property1;
private bool running1;
private List<DoubleAnimation> animation2;
private DependencyProperty property2;
private bool running2;
private int curent;
private UIElement element;
public AnimationQueue(UIElement element , DependencyProperty property )
{
curent = -1;
this.element = element;
animation1 = new List<DoubleAnimation>();
animation2 = new List<DoubleAnimation>();
this.property1 = property;
}
public AnimationQueue(UIElement element, DependencyProperty property1 , DependencyProperty property2)
{
curent = -1;
this.element = element;
animation1 = new List<DoubleAnimation>();
animation2 = new List<DoubleAnimation>();
this.property1 = property1;
this.property2 = property2;
}
public void queueAnimation(DoubleAnimation animation1, DoubleAnimation animation2)
{
animation1.Completed += (s, e) =>
{
running1 = false;
};
animation2.Completed += (s, e) =>
{
running2 = false;
};
this.animation1.Add(animation1);
this.animation2.Add(animation2);
}
public void start(int i)
{
if (animation1.Count != animation2.Count)
Console.WriteLine("Animation Queue not equal");
else
{
if (i == animation1.Count)
Console.WriteLine("Animation finished");
else if (i <= animation1.Count && i <= animation2.Count)
{
element.BeginAnimation(property1, animation1[i]);
element.BeginAnimation(property2, animation2[i]);
if (running1 == false && running2 == false)
{
i++;
start(i);
}
}
}
}
public void start()
{
curent = 0;
element.BeginAnimation(property1, animation1[curent]);
element.BeginAnimation(property2, animation2[curent]);
if(running1 == false && running2 == false)
start(curent++);
}
}`
In this class I add 2 animations for each point in the coordinate list . 1 to animate the x axis movement and 1 to anymate the y axis movement . The adding goes like this :
public void StartCourse()
{
int i = 0;
List<Point> coordinates = course.firstFuntion();
while (coordinates.Count != i)
{
queue1.queueAnimation(new DoubleAnimation(coordinates[i].X, new Duration(TimeSpan.FromMilliseconds(500))),
new DoubleAnimation(coordinates[i].Y, new Duration(TimeSpan.FromMilliseconds(500)))
);
i++;
}
queue1.start();
}
My problem is , I believe , in the AnimationQueue.Start() method. The program stars the animation , however it only executes the first animation . After that it stops . I tried to make use of the animation.Completed Event Handler but to no success.
BeginAnimation starts animation asynchrously. I suppose this may help:
private class AnimationQueue
{
private List<DoubleAnimation> animation1 ;
private DependencyProperty property1;
private bool running1;
private List<DoubleAnimation> animation2;
private DependencyProperty property2;
private bool running2;
private int curent;
private UIElement element;
public AnimationQueue(UIElement element , DependencyProperty property )
{
curent = -1;
this.element = element;
animation1 = new List<DoubleAnimation>();
animation2 = new List<DoubleAnimation>();
this.property1 = property;
}
public AnimationQueue(UIElement element, DependencyProperty property1 , DependencyProperty property2)
{
curent = -1;
this.element = element;
animation1 = new List<DoubleAnimation>();
animation2 = new List<DoubleAnimation>();
this.property1 = property1;
this.property2 = property2;
}
public void queueAnimation(DoubleAnimation animation1, DoubleAnimation animation2)
{
this.animation1.Add(animation1);
this.animation2.Add(animation2);
animation1.Completed += (s, e) =>
{
if (this.animation1.Contains(animation1))
{
int index1 = this.animation1.IndexOf(animation1);
if (index1 + 1 < this.animation1.Count)
{
element.BeginAnimation(property1, animation1[index1 + 1]);
}
}
};
animation2.Completed += (s, e) =>
{
if (this.animation2.Contains(animation2))
{
int index2 = this.animation2.IndexOf(animation2);
if (index2 + 1 < this.animation2.Count)
{
element.BeginAnimation(property2, animation2[index2 + 1]);
}
}
};
}
public void start()
{
curent = 0;
element.BeginAnimation(property1, animation1[curent]);
element.BeginAnimation(property2, animation2[curent]);
}
}`

How to get a WPF datagrid column resize event?

I want to dynamically load and store the Datagrid column widths from my ini file. Write to my inifile for every resize of the column width. Which event can i ues for this. Could any body give any Suggetions or sample code for this.
i use apllicationsettings within a behavior for such things and save the information on application exit.
usage
<DataGrid>
<i:Interaction.Behaviors>
<local:DataGridBehavior GridSettings="{Binding Source={x:Static local:MySettings.Instance},Mode=OneWay}" />
</i:Interaction.Behaviors>
</DataGrid>
settings
[SettingsManageabilityAttribute(SettingsManageability.Roaming)]
public sealed class MySettings: ApplicationSettingsBase, IGridSettings
{
private static readonly Lazy<MySettings> LazyInstance = new Lazy<MySettings>(() => new KadiaSettings());
public static MySettingsInstance { get { return LazyInstance.Value; } }
[UserScopedSettingAttribute()]
[DefaultSettingValue("")]
[SettingsSerializeAs(SettingsSerializeAs.Xml)]
public SerializableDictionary<string, int> GridDisplayIndexList
{
get { return (SerializableDictionary<string, int>)this["GridDisplayIndexList"]; }
set { this["GridDisplayIndexList"] = value; }
}
[UserScopedSettingAttribute()]
[DefaultSettingValue("")]
[SettingsSerializeAs(SettingsSerializeAs.Xml)]
public SerializableDictionary<string, Visibility> GridColumnVisibilityList
{
get { return (SerializableDictionary<string, Visibility>)this["GridColumnVisibilityList"]; }
set { this["GridColumnVisibilityList"] = value; }
}
[UserScopedSettingAttribute()]
[DefaultSettingValue("")]
[SettingsSerializeAs(SettingsSerializeAs.Xml)]
public SerializableDictionary<string, double> GridColumnWidthList
{
get { return (SerializableDictionary<string, double>)this["GridColumnWidthList"]; }
set { this["GridColumnWidthList"] = value; }
}
private MySettings()
{
Application.Current.Exit += OnExit;
}
private void OnExit(object sender, ExitEventArgs e)
{
this.Save();
}
}
public interface IGridSettings: INotifyPropertyChanged
{
SerializableDictionary<string, int> GridDisplayIndexList { get; }
SerializableDictionary<string, Visibility> GridColumnVisibilityList { get; }
SerializableDictionary<string, double> GridColumnWidthList { get; }
}
[XmlRoot("Dictionary")]
public class SerializableDictionary<TKey, TValue>: Dictionary<TKey, TValue>, IXmlSerializable
{
#region IXmlSerializable Members
public System.Xml.Schema.XmlSchema GetSchema()
{
return null;
}
public void ReadXml(System.Xml.XmlReader reader)
{
var keySerializer = new XmlSerializer(typeof(TKey));
var valueSerializer = new XmlSerializer(typeof(TValue));
bool wasEmpty = reader.IsEmptyElement;
reader.Read();
if (wasEmpty)
return;
while (reader.NodeType != System.Xml.XmlNodeType.EndElement)
{
reader.ReadStartElement("item");
reader.ReadStartElement("key");
var key = (TKey)keySerializer.Deserialize(reader);
reader.ReadEndElement();
reader.ReadStartElement("value");
var value = (TValue)valueSerializer.Deserialize(reader);
reader.ReadEndElement();
this.Add(key, value);
reader.ReadEndElement();
reader.MoveToContent();
}
reader.ReadEndElement();
}
public void WriteXml(System.Xml.XmlWriter writer)
{
var keySerializer = new XmlSerializer(typeof(TKey));
var valueSerializer = new XmlSerializer(typeof(TValue));
foreach (TKey key in this.Keys)
{
writer.WriteStartElement("item");
writer.WriteStartElement("key");
keySerializer.Serialize(writer, key);
writer.WriteEndElement();
writer.WriteStartElement("value");
TValue value = this[key];
valueSerializer.Serialize(writer, value);
writer.WriteEndElement();
writer.WriteEndElement();
}
}
#endregion
}
behavior
public class DataGridBehavior : Behavior<DataGrid>
{
public static readonly DependencyProperty GridSettingsProperty =
DependencyProperty.Register("GridSettings", typeof(IGridSettings), typeof(DataGridBehavior), null);
public IGridSettings GridSettings
{
get { return (IGridSettings)GetValue(GridSettingsProperty); }
set { SetValue(GridSettingsProperty, value); }
}
public DataGridICollectionViewSortMerkerBehavior()
{
Application.Current.Exit += CurrentExit;
}
private void CurrentExit(object sender, ExitEventArgs e)
{
SetSettings();
}
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.Loaded += AssociatedObjectLoaded;
AssociatedObject.Unloaded += AssociatedObjectUnloaded;
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.Loaded -= AssociatedObjectLoaded;
AssociatedObject.Unloaded -= AssociatedObjectUnloaded;
}
private void AssociatedObjectUnloaded(object sender, RoutedEventArgs e)
{
SetSettings();
}
void AssociatedObjectLoaded(object sender, RoutedEventArgs e)
{
var settings = GridSettings;
var columns = AssociatedObject.Columns.ToList();
var colCount = columns.Count;
foreach (var column in columns)
{
var key = column.Header.ToString();
if (settings.GridDisplayIndexList.ContainsKey(key))
{
//manchmal wird -1 als index abgespeichert
var index = settings.GridDisplayIndexList[key];
if(index > 0 && index < colCount)
column.DisplayIndex = index;
}
if (settings.GridColumnVisibilityList.ContainsKey(key))
{
column.Visibility = settings.GridColumnVisibilityList[key];
}
if (settings.GridColumnWidthList.ContainsKey(key))
{
column.Width = new DataGridLength(settings.GridColumnWidthList[key]);
}
}
}
private void SetSettings()
{
var settings = GridSettings;
foreach (var column in AssociatedObject.Columns)
{
var key = column.Header.ToString();
var displayindex = column.DisplayIndex;
var visibility = column.Visibility;
var width = column.ActualWidth;
if (settings.GridDisplayIndexList.ContainsKey(key))
{
settings.GridDisplayIndexList[key] = displayindex;
}
else
{
settings.GridDisplayIndexList.Add(key, displayindex);
}
if (settings.GridColumnVisibilityList.ContainsKey(key))
{
settings.GridColumnVisibilityList[key] = visibility;
}
else
{
settings.GridColumnVisibilityList.Add(key, visibility);
}
if (settings.GridColumnWidthList.ContainsKey(key))
{
settings.GridColumnWidthList[key] = width;
}
else
{
settings.GridColumnWidthList.Add(key, width);
}
}
}
}

How can i pass kinect tracking into another form

I have a kinect project in wpf and it uses skeleton stream that tracks the left and right hand of its users and allows me to hover over buttons.
I tried making a new form and just copying and pasting everything so i can create a new page but it didnt work, i think i may have to reference the methods used in the main page, but i am unsure.
I want to be able to use the skeleton stream alongside the hovering method in a new window
Any help would be appreciated - i apologize if this does not make sense i am a beginner
Code
public partial class MainWindow : Window
{
private KinectSensor _Kinect;
private WriteableBitmap _ColorImageBitmap;
private Int32Rect _ColorImageBitmapRect;
private int _ColorImageStride;
private Skeleton[] FrameSkeletons;
List<Button> buttons;
static Button selected;
float handX;
float handY;
public MainWindow()
{
InitializeComponent();
InitializeButtons();
kinectButton.Click += new RoutedEventHandler(kinectButton_Click);
this.Loaded += (s, e) => { DiscoverKinectSensor(); };
this.Unloaded += (s, e) => { this.Kinect = null; };
}
//initialize buttons to be checked
private void InitializeButtons()
{
buttons = new List<Button> { button1, button2, quitButton};
}
//raise event for Kinect sensor status changed
private void DiscoverKinectSensor()
{
KinectSensor.KinectSensors.StatusChanged += KinectSensors_StatusChanged;
this.Kinect = KinectSensor.KinectSensors.FirstOrDefault(x => x.Status == KinectStatus.Connected);
}
private void KinectSensors_StatusChanged(object sender, StatusChangedEventArgs e)
{
switch (e.Status)
{
case KinectStatus.Connected:
if (this.Kinect == null)
{
this.Kinect = e.Sensor;
}
break;
case KinectStatus.Disconnected:
if (this.Kinect == e.Sensor)
{
this.Kinect = null;
this.Kinect = KinectSensor.KinectSensors.FirstOrDefault(x => x.Status == KinectStatus.Connected);
if (this.Kinect == null)
{
MessageBox.Show("Sensor Disconnected. Please reconnect to continue.");
}
}
break;
}
}
public KinectSensor Kinect
{
get { return this._Kinect; }
set
{
if (this._Kinect != value)
{
if (this._Kinect != null)
{
UninitializeKinectSensor(this._Kinect);
this._Kinect = null;
}
if (value != null && value.Status == KinectStatus.Connected)
{
this._Kinect = value;
InitializeKinectSensor(this._Kinect);
}
}
}
}
private void UninitializeKinectSensor(KinectSensor kinectSensor)
{
if (kinectSensor != null)
{
kinectSensor.Stop();
kinectSensor.ColorFrameReady -= Kinect_ColorFrameReady;
kinectSensor.SkeletonFrameReady -= Kinect_SkeletonFrameReady;
}
}
private void InitializeKinectSensor(KinectSensor kinectSensor)
{
if (kinectSensor != null)
{
ColorImageStream colorStream = kinectSensor.ColorStream;
colorStream.Enable();
this._ColorImageBitmap = new WriteableBitmap(colorStream.FrameWidth, colorStream.FrameHeight,
96, 96, PixelFormats.Bgr32, null);
this._ColorImageBitmapRect = new Int32Rect(0, 0, colorStream.FrameWidth, colorStream.FrameHeight);
this._ColorImageStride = colorStream.FrameWidth * colorStream.FrameBytesPerPixel;
videoStream.Source = this._ColorImageBitmap;
kinectSensor.SkeletonStream.Enable(new TransformSmoothParameters()
{
Correction = 0.5f,
JitterRadius = 0.05f,
MaxDeviationRadius = 0.04f,
Smoothing = 0.5f
});
kinectSensor.SkeletonFrameReady += Kinect_SkeletonFrameReady;
kinectSensor.ColorFrameReady += Kinect_ColorFrameReady;
kinectSensor.Start();
this.FrameSkeletons = new Skeleton[this.Kinect.SkeletonStream.FrameSkeletonArrayLength];
}
}
private void Kinect_ColorFrameReady(object sender, ColorImageFrameReadyEventArgs e)
{
using (ColorImageFrame frame = e.OpenColorImageFrame())
{
if (frame != null)
{
byte[] pixelData = new byte[frame.PixelDataLength];
frame.CopyPixelDataTo(pixelData);
this._ColorImageBitmap.WritePixels(this._ColorImageBitmapRect, pixelData,
this._ColorImageStride, 0);
}
}
}
private void Kinect_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
{
using (SkeletonFrame frame = e.OpenSkeletonFrame())
{
if (frame != null)
{
frame.CopySkeletonDataTo(this.FrameSkeletons);
Skeleton skeleton = GetPrimarySkeleton(this.FrameSkeletons);
if (skeleton == null)
{
kinectButton.Visibility = Visibility.Collapsed;
}
else
{
Joint primaryHand = GetPrimaryHand(skeleton);
TrackHand(primaryHand);
}
}
}
}
//track and display hand
private void TrackHand(Joint hand)
{
if (hand.TrackingState == JointTrackingState.NotTracked)
{
kinectButton.Visibility = System.Windows.Visibility.Collapsed;
}
else
{
kinectButton.Visibility = System.Windows.Visibility.Visible;
DepthImagePoint point = this.Kinect.MapSkeletonPointToDepth(hand.Position, DepthImageFormat.Resolution640x480Fps30);
handX = (int)((point.X * LayoutRoot.ActualWidth / this.Kinect.DepthStream.FrameWidth) -
(kinectButton.ActualWidth / 2.0));
handY = (int)((point.Y * LayoutRoot.ActualHeight / this.Kinect.DepthStream.FrameHeight) -
(kinectButton.ActualHeight / 2.0));
Canvas.SetLeft(kinectButton, handX);
Canvas.SetTop(kinectButton, handY);
if (isHandOver(kinectButton, buttons)) kinectButton.Hovering();
else kinectButton.Release();
if (hand.JointType == JointType.HandRight)
{
kinectButton.ImageSource = "/Images/RightHand.png";
kinectButton.ActiveImageSource = "/Images/RightHand.png";
}
else
{
kinectButton.ImageSource = "/Images/LeftHand.png";
kinectButton.ActiveImageSource = "/Images/LeftHand.png";
}
}
}
//detect if hand is overlapping over any button
private bool isHandOver(FrameworkElement hand, List<Button> buttonslist)
{
var handTopLeft = new Point(Canvas.GetLeft(hand), Canvas.GetTop(hand));
var handX = handTopLeft.X + hand.ActualWidth / 2;
var handY = handTopLeft.Y + hand.ActualHeight / 2;
foreach (Button target in buttonslist)
{
Point targetTopLeft = new Point(Canvas.GetLeft(target), Canvas.GetTop(target));
if (handX > targetTopLeft.X &&
handX < targetTopLeft.X + target.Width &&
handY > targetTopLeft.Y &&
handY < targetTopLeft.Y + target.Height)
{
selected = target;
return true;
}
}
return false;
}
//get the hand closest to the Kinect sensor
private static Joint GetPrimaryHand(Skeleton skeleton)
{
Joint primaryHand = new Joint();
if (skeleton != null)
{
primaryHand = skeleton.Joints[JointType.HandLeft];
Joint rightHand = skeleton.Joints[JointType.HandRight];
if (rightHand.TrackingState != JointTrackingState.NotTracked)
{
if (primaryHand.TrackingState == JointTrackingState.NotTracked)
{
primaryHand = rightHand;
}
else
{
if (primaryHand.Position.Z > rightHand.Position.Z)
{
primaryHand = rightHand;
}
}
}
}
return primaryHand;
}
//get the skeleton closest to the Kinect sensor
private static Skeleton GetPrimarySkeleton(Skeleton[] skeletons)
{
Skeleton skeleton = null;
if (skeletons != null)
{
for (int i = 0; i < skeletons.Length; i++)
{
if (skeletons[i].TrackingState == SkeletonTrackingState.Tracked)
{
if (skeleton == null)
{
skeleton = skeletons[i];
}
else
{
if (skeleton.Position.Z > skeletons[i].Position.Z)
{
skeleton = skeletons[i];
}
}
}
}
}
return skeleton;
}
void kinectButton_Click(object sender, RoutedEventArgs e)
{
selected.RaiseEvent(new RoutedEventArgs(Button.ClickEvent, selected));
}
private void button1_Click(object sender, RoutedEventArgs e)
{
message.Content = "Button 1 clicked!";
}
private void button2_Click(object sender, RoutedEventArgs e)
{
message.Content = "Button 2 clicked!";
}
private void quitButton_Click(object sender, RoutedEventArgs e)
{
Application.Current.Shutdown();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
}
}
You can do this in a couple of different ways, and more ways then what is below.
You could pass a reference to the sensor itself to the new window when it is created:
public MainWindow()
{
// init code for window and Kinect
// show the second window
SecondWindow mySecondWindow = new SecondWindow(_Kinect);
mySecondWindow.Show();
// other stuff...
}
public class SecondWindow : Window
{
public SecondWindow(KinectSensor sensor)
{
// ... stuff
sensor.SkeletonFrameReady += SkeletonFrameReadyCallback;
// ... more stuff
}
}
Then subscribe to the SkeletonFrameReady callback in your second window. This might work for your situation if you are interacting with items in the seconds window.
Another way would be to create a public callback inside your second window and subscribe it to the SkeletonFrameReady event.
public MainWindow()
{
// init code for window and Kinect
// show the second window
SecondWindow mySecondWindow = new SecondWindow(_Kinect);
mySecondWindow.Show();
_Kinect.SkeletonFrameReady += mySecondWindow.SkeletonFrameReadyCallback;
}
I also notice in your code that you are firing events. If you are wanting to act on events from one window in a different window, you can subscribe to those custom events in the same mentioned above.

Resources