c# - How to detach from the Visual Tree in WPF -
i'm trying correctly remove uielement inlineuicontainer in order use in panel program keeps crashing message "specified visual child of visual or root of compositiontarget.".
i've created small application illustrate pain. in program, once randy button killed\deleted girlfriend, doesn't still detach parent, whom got find out uielementisland. , attempt add randy child of else crashes application (the apocalypse button proves point :) ). can click check randy's parents before\after deleting randy notice under uielementisland child, if detached whole problem\apocalypse should averted.
it's funny application copy , compile if it's fun! help\ideas appreciated!
the c# part:
using system; using system.collections.generic; using system.linq; using system.text; using system.threading.tasks; using system.windows; using system.windows.controls; using system.windows.data; using system.windows.documents; using system.windows.input; using system.windows.media; using system.windows.media.imaging; using system.windows.navigation; using system.windows.shapes; using system.windows.threading; namespace detachingfromuielementisland { /// <summary> /// interaction logic mainwindow.xaml /// </summary> public partial class mainwindow : window { public mainwindow() { initializecomponent(); } int t = 0; static string[] info = new string[] { "okay, lets have look...", "checking." , "checking..", "checking...", "seen it!" }; /// <summary> /// makes app fancy :) /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void timer_tick(object sender, eventargs e) { display.text = info[t]; if (t == 0) timer.interval = new timespan(0, 0, 0, 0, 300); t++; if (t >= 4) { t = 0; timer.stop(); display.text = getrandysparent(); } } private void deleterandy_click(object sender, routedeventargs e) { // might bug. // maybe there's better way this. // if there visualtreehelper.remove(). randy_container.child = null; display.text = "haha! killed randy!!! he'll never chance" + "\n hurt woman again!"; display.background = brushes.violet; end.visibility = system.windows.visibility.visible; } dispatchertimer timer = null; /// <summary> /// check if randy still attached uielementisland /// </summary> /// <returns></returns> private string getrandysparent() { // check visual tree see if randy removed dependencyobject dp = visualtreehelper.getparent(randy); string text = string.empty; if (dp != null) { display.background = brushes.lightgreen; text = "randy's dad mr " + dp.tostring(); } else { // should you'll when code works display.background = brushes.red; text = "weird...randy doesn't seem have dad..."; } return text; } private void findparents_click(object sender, routedeventargs e) { display.background = brushes.yellow; // creates timer display fancy stuff // , randy's. // prove button works. timer = new dispatchertimer(); timer.start(); timer.tick += timer_tick; timer.interval = new timespan(0, 0, 0, 0, 700); } private void randy_click(object sender, routedeventargs e) { // randy introduce himself display.text = "hi, i'm randy!!!"; display.background = brushes.orange; } private void end_click(object sender, routedeventargs e) { // if randy removed properly, not crash application. stackpanel s = new stackpanel(); s.children.add(randy); // crash!!! } } } the xaml:
<window x:class="detachingfromuielementisland.mainwindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" title="mainwindow" height="350" width="525"> <flowdocument isenabled="true" x:name="document"> <paragraph> <inlineuicontainer x:name="randy_container"> <!--meet randy--> <button name="randy" content="i randy, button" click="randy_click" tooltip="meet randy"/> </inlineuicontainer> <linebreak/> <linebreak/> <inlineuicontainer x:name="container2"> <!--meet randy's ex girlfriend--> <button name="deleterandy" content="randy dumped me girl :(, click me delete him" click="deleterandy_click" tooltip="meet randy's ex girlfriend"/> </inlineuicontainer> <linebreak/> <linebreak/> <inlineuicontainer x:name="container3"> <!--he can find randy's parents--> <button name="findparents" content="click me find randy's parents" click="findparents_click" tooltip="he can find randy's parents"/> </inlineuicontainer> <linebreak/> <linebreak/> <inlineuicontainer x:name="apocalypse"> <!--end world, crash application--> <button x:name="end" content="avenge randy's death" click="end_click" tooltip="end world, crash application" visibility="hidden"/> </inlineuicontainer> </paragraph> <paragraph> <inlineuicontainer> <textblock x:name="display" foreground="black"/> </inlineuicontainer> </paragraph> </flowdocument> </window> the whole code supposed shorter this, spiced make bit fun. hope brightened someone's day little. still, me :).
answer: derive randy's inlineuicontainer follows:
public class derivedinlineuicontainer : inlineuicontainer { public derivedinlineuicontainer() { } public void removefromlogicaltree(frameworkelement f) { this.removelogicalchild(f); } } now kill randy time, , add him uielement heaven (the stackpanel):
randy_container.removefromlogicaltree(randy); idisposable disp = visualtreehelper.getparent(randy) idisposable; if (disp != null) disp.dispose(); // poor randy going heaven... stackpanel heaven = new stackpanel(); heaven.add(randy); thanks everyone.
removing visual parent doesn't seem help:
private void end_click(object sender, routedeventargs e) { idisposable disp = visualtreehelper.getparent(randy) idisposable; if (disp != null) disp.dispose(); dependencyobject parent = visualtreehelper.getparent(randy); if (parent == null) messagebox.show("no parent"); // if randy removed properly, not crash application. stackpanel s = new stackpanel(); s.children.add(randy); } so either create new button:
public mainwindow() { initializecomponent(); randy_container.child = createrandybutton(); } private void end_click(object sender, routedeventargs e) { stackpanel s = new stackpanel(); s.children.add(createrandybutton()); } private button createrandybutton() { button button = new button { name = "randy", content = "i randy, button", tooltip = "meet randy" }; button.click += randy_click; return button; } ...or hide suggested @sinatr.
Comments
Post a Comment