Remove button from memory which is removed from Grid - wpf

In my application, i am generating multiple buttons at run time and add it to grid as following
for (int i = 0; i < ListOfMainCategories.Count; i++)
{
clsMainCategory tempCat = (clsMainCategory)ListOfMainCategories[i];
ButtonMainMenuCat btn = CreateMainButton(tempCat.CatTitle, i);
btn.Margin = new Thickness(0, 1, 0, 1);
btn.TabIndex = TabIndexNo;
if (i == 0)
{
buttonHomeMenu = btn;
}
btn.AddHandler(ButtonMainMenuSubSubCat.GotKeyboardFocusEvent, new RoutedEventHandler(ButtonMainMenuGotFocus), handledEventsToo: false);
// stackTableViewMainMenu.Children.Add(btn);
Grid.SetRow(btn, 1);
Grid.SetColumn(btn, i + 1);
gridHeader.Children.Add(btn);
}
After on particular event I removed all of these buttons from Grid.
gridHeader.Children.RemoveRange(0, gridHeader.Children.Count);
Here i Think i also need to Remove or dispose or unload these button from Memory. So How can i do this task ? Please suggest

Yuo can't dispose of the button in the classical sense as there is nothing to dispose. You are dealing with managed code here. The memory allocation will be cleared up by the garbage collector as long as there are no references. In the code above you are keeping a reference to the button through the routed event handler so call btn.RemoveHandler before you remove it from the Grid.
You could take a look at MSDN guidance on the WeakEvent pattern here: http://msdn.microsoft.com/en-us/library/aa970850

Related

SharpDX.WPF Increasing memory usage during rendering

I have started working with DirectX in WPF app. My first step was to use simple library:
SharpdDX.WPF. Based on samples I've implemented WPF control drawing simple line. SharpDX.WPF uses D3DImage to render images in WPF.
Unfortunately application's memory increasing all time.
I implemented class TestControlRenderer : D3D10.
Vertex shader is initialized like:
var sizeInBytes = dataLength * sizeof(int) * 3;
var bufferDescription = new BufferDescription(
sizeInBytes,
ResourceUsage.Dynamic,
BindFlags.VertexBuffer,
CpuAccessFlags.Write,
ResourceOptionFlags.None);
using (var stream = new DataStream(sizeInBytes, true, true))
{
stream.Position = 0;
_graphDataVertexBuffer = new SharpDX.Direct3D10.Buffer(Device, stream, bufferDescription);
}
Device.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(_graphDataVertexBuffer, sizeof(int) * 3, 0));
Device.InputAssembler.PrimitiveTopology = PrimitiveTopology.LineStrip;
Then constant buffer with parameters used in shader:
_controlInfoConstantBuffer = new ConstantBuffer<ControlParamsShaderData>(Device);
Device.VertexShader.SetConstantBuffer(0, _controlInfoConstantBuffer.Buffer);
To init animation Reset method was overriden like that:
base.Reset(args);
if (args.RenderSize.Width == 0) return;
_drawArgs = args;
InitVertexBuffer(dataLength);
_controlInfoConstantBuffer.Value = new ControlParamsShaderData
{
SamplesInControl = dataLength,
MinSignalDataY = -1500,
MaxSignalDataY = 1500
};
Device.VertexShader.SetConstantBuffer(0, _controlInfoConstantBuffer.Buffer);
The last step is RenderScene method:
public override void RenderScene(DrawEventArgs args)
{
if (args.RenderSize.Width == 0) return;
Device.ClearRenderTargetView(RenderTargetView, Color.Transparent);
using (var stream = _graphDataVertexBuffer.Map(MapMode.WriteDiscard, SharpDX.Direct3D10.MapFlags.None))
{
for (int i = 0; i < Data.Length; i++)
{
stream.Write(new Vector3(i, Data[i], 0));
}
}
_graphDataVertexBuffer.Unmap();
Device.Draw(Data.Length, 0);
}
Rendering is controlled by DispatcherTimer where OnTickMethod updates array with points coordinates and then invoke Render() method.
My question is simply, is that memory leak or something is created on each render iteration?
I don't change backbuffer or create another objects. Only change Data array, update it to GPU and Shaders process it to display.
My case is to display about 30 wpf controls width DirectX on one screen. Controls are with simple but realtime animation. Is that possible in that way?
Most likely you are leaking resources. You can see this by setting the static configuration property
SharpDX.Configuration.EnableObjectTracking = true;
then calling
SharpDX.Diagnostics.ObjectTracker.ReportActiveObjects()
at various points in your application lifetime to see if anything is leaking (at least on the SharpDX side). You can edit your code to make sure to dispose these objects. Only enable object tracking while debugging - it hurts performance.
SharpDX used to release COM objects when the finalizer ran if the object had not already been Diposed (at least as in version 2.4.2), but later disabled that (they detail why in one of their changelogs, I forget which one).
Additionally, DirectX requires that you release objects in the reverse order they were created - this can create hard-to-debug memory leaks. So when your code is
var device = new Devie(...);
var effect = new Effec(Device, byteCode);
technique = effect.GetTechniqueByName(techniqueName);
inputLayout = new InputLayout(Device, _technique.GetPassByIndex(0).Description.Signature, ...);
then your dispose code has to be
_inputLayout.Dispose();
_technique.Dispose();
_effect.Dispose();
_device.Dispose();

Wpf datagrid don't refresh dynamic

I have the following code, where TabResultadoBusqueda is a Datagrid.
My problem is when I click in one button of this window , it's frozen until the operation finishes.
I would like that the user could be doing other things while Datagrid is loading, as the time to perform the operation is 1 min,.
Example code event Click in one Button:
TabResultadoBusqueda.ItemsSource = null;
TabResultadoBusqueda.ItemsSource = (IEnumerable<articuloPOCO>)cambioDeArticuloListaAArticuloPOCOlista(m.todosArticulosPAGINADOS(0, 50));
TabResultadoBusqueda.Dispatcher.BeginInvoke(DispatcherPriority.Background,
new Action(
() => aaaa1()
)
);
code of aaaa1:
for (int j = 2; j < 15; j++)
{
((List<articuloPOCO>)TabResultadoBusqueda.ItemsSource).AddRange((IEnumerable<articuloPOCO>)cambioDeArticuloListaAArticuloPOCOlista(m.todosArticulosPAGINADOS(j, 50)));
TabResultadoBusqueda.Items.Refresh();
}
Any help will be good.
Do your long running operation on a separate thread. This will keep your UI thread unblocked and responsive. It looks like a BackgroundWorker will be good for your situation. Read about it here http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx

Custom panel layout doesn't work as expected when animating (WPF)

I've got a custom (and getting complex) TabControl. It's a gathering of many sources, plus my own wanted features. In it is a custom Panel to show the headers of the TabControl. Its features are to compress the size of the TabItems until they reached their minimum, and then activates scrolling features (in the Panel, again). There is also another custom panel to hold a single button, that renders on the right of the TabItems (it's a "new tab" button).
It all works great, until I try to animate the scrolling.
Here are some relevant snippets :
In the CustomTabPanel (C#, overriding Panel and implementing IScrollInfo):
private readonly TranslateTransform _translateTransform = new TranslateTransform();
public void LineLeft()
{
FirstVisibleIndex++;
var offset = HorizontalOffset + _childRects[0].Width;
if (offset < 0 || _viewPort.Width >= _extent.Width)
offset = 0;
else
{
if (offset + _viewPort.Width > _extent.Width)
offset = _extent.Width - _viewPort.Width;
}
_offset.X = offset;
if (_scrollOwner != null)
_scrollOwner.InvalidateScrollInfo();
//Animate the new offset
var aScrollAnimation = new DoubleAnimation(_translateTransform.X, -offset,
new Duration(this.AnimationTimeSpan), FillBehavior.HoldEnd) { AccelerationRatio = 0.5, DecelerationRatio = 0.5 };
aScrollAnimation.Completed += ScrollAnimationCompleted;
_translateTransform.BeginAnimation(TranslateTransform.XProperty, aScrollAnimation , HandoffBehavior.SnapshotAndReplace);
//End of animation
// These lines are the only ones needed if we remove the animation
//_translateTransform.X = -offset;
//InvalidateMeasure();
}
void ScrollAnimationCompleted(object sender, EventArgs e)
{
InvalidateMeasure();
}
the _translateTransform is initialized in the constructor :
base.RenderTransform = _translateTransform;
Again, everything is fine if I remove the animation part and just replace it with the commented out lines at the end.
I must also point out that the problem is NOT with the animation itself. That part works out well. The problem is about when I remove some tab items : all the layout then screws up. The TranslateTransformation seems to hold on some wrong value, or something.
Thanks in advance.
Well. As it's often the case, I kept working on the thing, and... answered myself.
Could still be useful for other people, so here was the catch. In the line :
var aScrollAnimation = new DoubleAnimation(_translateTransform.X, -offset, new Duration(this.AnimationTimeSpan), FillBehavior.HoldEnd)
{ AccelerationRatio = 0.5, DecelerationRatio = 0.5 };
the FillBehavior should have been FillBehavior.Stop.
As easy as that!

While pausing a Storyboard, Does the Property being animated get locked ? Does the AnimationClock stops?

ParallelTimeline OTimelineAnimation = new ParallelTimeline();
for (int i = 0; i < _Bubbles.Count; i++)
{
_StryBrd.Children.Clear();
PointAnimation ToMovePointAnim = new PointAnimation();
ToMovePointAnim.From = _Bubbles[i].CurrentPoint;
ToMovePointAnim.To = _Bubbles[i].ToNextPoint;
ToMovePointAnim.Duration = new Duration(TimeSpan.FromSeconds(1.5));
ToMovePointAnim.FillBehavior = FillBehavior.Stop;
Storyboard.SetTarget(ToMovePointAnim, _Bubbles[i].CurrentElement);
Storyboard.SetTargetProperty(ToMovePointAnim, new PropertyPath(ScatterViewItem.CenterProperty));
OTimelineAnimation.Children.Add(ToMovePointAnim);
_Bubbles[i].CurrentElement.Center = _Bubbles[i].ToNextPoint;
_Bubbles[i].CurrentPoint = _Bubbles[i].ToNextPoint;
_Bubbles[i].ToNextPoint = GetToNextPoint(_Bubbles[i].ToNextPoint);
}
_StryBrd.Children.Add(OTimelineAnimation);
_StryBrd.Begin(this, true);
// At another part X, I call the following
_StryBrd.Pause(this);
// At another part Y, I call the following
_StryBrd.Resume(this);
Problem:
While I try to drag any of these "ScatterViewItem" elements which internally ( I guess ! ) it is accessing the "ScatterViewItem.CenterProperty" somehow to change the position of the elements, its not being dragged.
Is this the default behaviour for pausing a storyboard ? ( To lock the property from being changed )
I hope I had clarified enough, Thank all in advance
Well, animations have quite extreme precedence, you cannot modify animated properties, even when paused. Just setting a property after an animation is trouble enough, here you also would need to get rid of the animation to change it.

How to change the direction of wpf marquee dynamically?

I want to change the direction of my marquee on changeDirection button click.
My code for changing direction is :
private void changeDirection_click(object sender, RoutedEventArgs e)
{
if (_marqueeType == MarqueeType.RightToLeft)
{
_marqueeType = MarqueeType.LeftToRight;
StartMarqueeing(_marqueeType);
}
else if (_marqueeType == MarqueeType.LeftToRight)
{
_marqueeType = MarqueeType.RightToLeft;
StartMarqueeing(_marqueeType);
}
}
And code for start marquee is :
public void StartMarqueeing(MarqueeType marqueeType)
{
double height = canMain.ActualHeight - marqueeList.ActualHeight;
marqueeList.Margin = new Thickness(0, 0, 0, 0);
doubleAnimation.From = -marqueeList.ActualWidth;
doubleAnimation.To = canMain.ActualWidth;
doubleAnimation.RepeatBehavior = RepeatBehavior.Forever;
doubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(_marqueeTimeInSeconds));
if (marqueeType == MarqueeType.RightToLeft)
{
Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath("(Canvas.Right)"));
_storyBoard.Children.Add(doubleAnimation);
_storyBoard.Begin(marqueeList, true);
}
else if (marqueeType == MarqueeType.LeftToRight)
{
Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath("(Canvas.Left)"));
_storyBoard.Children.Add(doubleAnimation);
_storyBoard.Begin(marqueeList, true);
}
}
Now here I am able to change the direction from Right to Left only first time.
But when I am change it from Left to Right it’s not changing the marquee position Left to Right.
It looks like you left out a _storyboard = new Storyboard(), perhaps at the top of the StartMarqueeing method.
From what I see it appears that every call to StartMarqueeing will add an additional DoubleAnimation to the storyboard, then start it again. So all the old DoubleAnimations will be recreated, and it looks like they take precedence.
Try creating a new Storyboard object each time, not just re-using it and adding to its children collection.
Update
Oh, now I see the problem. You should not be setting both (Canvas.Left) and (Canvas.Right). Use only one of the two: That's all you need anyway, and using both will give the Canvas conflicting instructions. Traditionally people use (Canvas.Left). I think that's what Canvas selects, which is what is causing your asymmetry.
You may wonder why I say you are using both when you don't think your two animations every run at the same time. Actually they do: The first animation runs then holds the value on the animated property until it is removed or bumped off by another animation. If the second animation then runs and modifies a different property it doesn't bump off the first animation so the first animation's value is still present.
The bottom line is, using (Canvas.Left) on both animations should fix it as long as you are using the default HandoffBehavior.SnapshotAndReplace.

Resources