Specified element is already the logical child of another element - wpf

This question is related to following thread.
Prism RegionAdapter - Removing then Adding View
My post to this thread was deleted my admin, saying it was answered and I need to start new thread. Please let me know if any of you have solved this issue.
My deleted post was...
How did you manage to get rid of "Specified element is already the logical child of another element. Disconnect it first." error with closing event. I tried the same thing, on closing I remove the dockablecontent from the documentpane. But it doesn't help I keep getting this error. Once I remove the view, and then later try to add it again the same way you are adding, I get this error.
Please help me, I am not sure what am I missing. I have wasted so much of time trying to get around it but no luck yet.
Here is the code I am using:
<ad:DockableContent ...
x:Name="viewRoot"
IsCloseable="True" HideOnClose="False"
Title="{Binding Title}">
<ContentControl Grid.Row="1" Content="{Binding View}"/>
</Grid>
</ad:DockableContent>
It gets used inside this:
<ad:DockingManager x:Name="DockingManagerControl" Grid.Column="1">
<ad:ResizingPanel x:Name="MainResizingPanel" ResizeWidth="*" ResizeHeight="*" Orientation="Horizontal">
<ad:DockablePane ad:ResizingPanel.ResizeWidth="0.25*" prism:RegionManager.RegionName="ProjectBrowserRegion"/>
<ad:ResizingPanel x:Name="PespectiveResizingPanel" ResizeWidth="0.75*" ResizeHeight="*" Orientation="Horizontal">
<ad:DocumentPane x:Name="DockablePaneControl"/>
</ad:ResizingPanel>
</ad:ResizingPanel>
</ad:DockingManager>
View content bindings are UI element which comes from separate dlls, So I don't have them as View/ViewModel pair. So I can't use ContentTemplate+DataContext way here. Things load nicely, but use can select/deselect these views. So if a view has been opens the view selection dialog again, then I clear all views (I remove it from DockablePaneControl Items.Clear()), and add the selected views again (DockablePaneControl Items.Add()), then I get this error.

Usually this occurs because you are trying to assign the same control to two different parents.
I often see this issue with Styles, where a non-template property that contains Controls is set in a Style, such as ContentControl.Content, or DataGridColumn.Header
For example, if your style sets ContentControl.Content, and you add two ContentControls to your Window, you'll encounter this error because the style is trying to assign the same controls inside the Content section of both ContentControls. The fix is to set a template style, such as ContentControl.ContentTemplate instead of ContentControl.Content. I like to say this is like giving multiple people the same cookie to it - it just doesn't work. You have to give them each the cookie cutter (template) instead so they can make their own.
I actually see questions about this error so much that I wrote a blog post about it

Related

LayoutInformation.GetLayoutSlot( Panel ).Width may return 0 if I dont call UpdateLayout()

When opening a new panel, at some point its Loaded event is raised. In here, I try to call
LayoutInformation.GetLayoutSlot( Parent as Panel ).Width
According to some guy the Loaded event is a prerequisite so that the layout is calculated etc., but I have met that condition. N.b. Loaded is called from root to children.
I tried invoking manually UpdateLayout() which does the job, but still I don't get why it doesn't work by itself.
Does anyone have any clue?
N.b. it seems to work when I call the method on my Parents' Parent!
Update
Im using a panel that has some width and height set. Then, I open and create a new canvas that has a panel. I want the most inner panel to stretch the available space - sometimes I get a proper value and sometimes not.
Im just trying to understand why it is not consistent, it seems to occur when a lot of processing is going on.
Reading the FrameworkElement.Loaded event, I noticed this snippet:
Be careful of reentrancy if your handler resets any properties that are interpreted by the layout system to mean that a new layout pass is required. (You might need to check the FrameworkPropertyMetadata values on the property if you are unsure of which properties can require a new layout pass if they are changed.)
My guess is that maybe you are, or a child control, or something of that nature is requiring a new layout pass once binding are hooking up and properties are getting changed. With that being said, this sounds like usual behavior and your best bet is to call UpdateLayout() to ensure that the control is correctly sized. I ran into the Layout which might be useful.
Also, notice this:
<Grid Width="0">
<Canvas x:Name="Parent"
Background="Red"
Width="10"
Loaded="Parent_Loaded">
<Canvas x:Name="Child"
Background="Yellow"
Width="20"
Height="20"
Loaded="Child_Loaded" />
</Canvas>
</Grid>
Calling LayoutInformation.GetLayoutSlot(Parent as Panel).Width; will return 0, though all the objects will appear. Though, if you make the Parent Canvas a StackPanel instead, you won't see anything appear. This shows that Canvas has special layout logic (it doesn't inherit layout properties). This is why showing more XAML might help us determine a more definitive solution.

TextBox inputing data issue with MVVM Light.?

I am working on WPF MvvmLight application and once I click on first page it navigates to second page. The second page has a textbox on which the focus is set. On this textbox, I am not able to put any data or any character. But I can do copy and paste. What might be the reason for this strange behavior.
<TextBox VerticalAlignment="Center" x:Name="txtsearchYouTube" Height="25"
Margin="100,0,100,0" Canvas.Top="275" Width="500"
Loaded="txtsearchYouTube_Loaded" Canvas.Left="50"
Text="{Binding SeachKeyWord,Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}"/>
1) The Binding is not the issue, in fact even if it is wrong, you will still be able to write in that TextBox, it just won't be put in SearchKeyWord. By the way, you mispelled it (you forgot an R in seaRch).
2) If you're really only setting the focus on the loaded event, and nothing else, then it's not the problem either.
3) MVVM Light is just a conveniency framework, it does not alter WPF for you as it just provides tools, it definitely doesn't mess with TextBoxes.
That said, here is what I would check in your situation:
If SearchKeyWord is a dependency property look where it is declared to see if there is a callback/coercevalue/validatevalue declared. Since the binding is two-way, it could very well always invalidate the values recieved (preventing you from actually writing anything in there)
Check all the way up your visual tree, for any implicit styles for the TextBox type. They could have triggers that mess up with your data.
Hope this helps,
Bab.
i dont know whats wrong with your code. but you can help your self. so just remove your binding and loaded event and check if you can put any data in your textbox.
if yes pls post all code from your event and viewmodel otherwise its hard to help.
you wrote you can copy and paste? what does it mean? your textbox show the text you paste in? or your viewmodel got the pasted value?
EDIT: you can also use Snoop to check your textbox binding and properties at runtime.

WPF: Adorning a ViewModel?

I have these ViewModels: RecordViewModel, ComponentViewModel where RecordViewModel essentially is a container for several ComponentViewModels.
The display of these ViewModels is currently handled by DataTemplates that look something like this:
<DataTemplate DataType="{x:Type vm:RecordViewModel}" >
<ItemsControl ItemsSource={Binding Components} />
</DataTemplate>
<DataTemplate DataType="{x:Type vm:ComponentViewModel}" >
<TextBox Text={Binding Name} />
</DataTemplate>
What I wanted to provide now is a way to change the order the ComponentViewModels are displayed and to remove a certain ComponentViewModel from the list. I started out doing that by manipulating the DataTemplate of the ComponentViewModel and adding buttons that provided these functions (the click would then trigger a method on the ComponentViewModel that would (through a reference "Parent" to the RecordViewModel) call a method on the RecordViewModel to perform the operation (like component.Parent.DeleteComponent(this)).
The problem with this in my oppinion is that it is really the Record that should manipulate the Components position/remove a Component and not the Component itself.
So I thought about using an adorner that attaches to the RecordViewModel and renders the buttons to provide the functionality (remove, move up, move down) for each of the ComponentViewModels.
The problem however is that these adorners need to take a reference to a Control-derivate which they adorn (which was ok I would just bind to the ItemsControl in the Record-DataTemplate) however the problem appears when I want to show the buttons in the right position for each ComponentViewModel. I only have a reference to the given ComponentViewModels and not to their visual representation (the thing defined in the DataTemplate) so I have no way of knowing where to place the 3 buttons.
Is there a way to work around this? Or is it possible that for these requirements using ViewModels/DataTemplates is just not a good idea and should I therefore use Control-derivates/ControlTemplates?
Thanks in advance!
Coming up with wacky architectural hacks that you can employ to keep your view model elegant and simple is missing the point. The view model is the wacky architectural hack.
The only reason - seriously, the only reason - that the view model exists is to model the view. Does the view have buttons that trigger commands? The commands belong in the view model.
Thinking, "it's really the Record's responsibility to move Components" seems sensible on its face, but it's actually an indication that you're losing track of why you even created a view model in the first place. Does the Component view have a "Move Up" button? Then the Component view model needs a "Move Up" command that you can bind the button to. Because that's what the Component view model is for.
I'm being emphatic about this because this is the third or fourth question I've seen this week from WPF developers who seem to have gone down so deeply down the rabbit hole of the MVVM pattern that they've forgotten why it exists.
If your goal is to have a Command on the parent ViewModel that acts on an element of the child ViewModel, you can do this by using a RelativeSource binding on Command and passing the item as Command Parameter:
<DataTemplate DataType="{x:Type vm:ComponentViewModel}" >
<Button
Command="{Binding DataContext.RemoveCommand,
RelativeSource={RelativeSource AncestorType=ItemsControl}}"
CommandParameter="{Binding}"
Content="{Binding Name}"/>
</DataTemplate>
The RelativeSource binding will find the ItemsControl, so the DataContext property will be your RecordViewModel. The CommandParameter will be the individual ComponentViewModel, so your ICommand implementation would be:
DeleteComponent((ComponentViewModel)parameter);
it is really the Record that should manipulate the Components position/remove a Component and not the Component itself
As far as your model objects go, that's probably true. However, the ViewModels are all about presentation, and the buttons are kind of part of a Component's presentation. So I think it could be acceptable for the ComponentViewModel to have a reference to its parent RecordViewModel, to enable this scenario, even if it wouldn't be appropriate for the Component to have a reference to its parent Record.
But consider that, in your scenario, maybe the ComponentViewModel has too many responsibilities. It belongs to the collection (because it's mutating the collection), and it belongs to the element in the collection (because it's showing the Component's name in a TextBox). It sounds like it's this dual responsibility that's bothering you. So break it up. Make RecordViewModel contain RecordElementViewModels, each of which knows how to remove itself from the Record; and each RecordElementViewModel contains a ComponentViewModel. On the view side, it sounds like your UI would be composed the same way: an outer panel with a Delete button, and then another control or panel inside that, presenting the Component's properties.
Now, for the example you posted, where Component's view is just a TextBox, I wouldn't bother splitting the ViewModel into two parts. But for a more complex example, it might make a lot of sense.
To specifically answer your question about adorning:
You're getting into changing the way a DataTemplate-d element is laid out, which means you're not just layering an adorner on top of the element, you're actually wanting to insert a panel into the visual tree that imposes its own layout onto the DataTemplate (which becomes a child of the new panel). I'll admit that I haven't used adorners, but that doesn't seem to be what they're for.
The best way to do this, IMO, is to have your DataTemplate generate the parent panel, buttons and all -- which leads back to wanting the functionality on the ComponentViewModel, or perhaps splitting ComponentViewModel's responsibilities (see my other answer).

How to create databinding over two xaml files?

I am trying to come to a working understanding of how databinding works, but even after several tutorials I only have a basic understanding of how databinding works. Thus this question might seem fundamental to those more familiar with silverlight. Even if it is trivial, please point me to some tutorial that deals with this problem. All that I could find simply solved this via adding the data binding on a parent page.xaml (that i must not use in my case).
For the sake of this example let us assume, that we have 5 files:
starter.cs
button1.xaml + codeBehind
button2.xaml + codeBehind
The two buttons are generated in code in the starter(.cs) file, and then added to some MapLayer
button1 my_button1 = new button1();
button2 my_button1 = new button2();
someLayer.Children.Add(my_button1);
someLayer.Children.Add(my_button2);
My aim is to connect the two buttons, so that they always display the same "text" (i.e. my_button1.content==my_button2.content = true;). Thus when something changes my_button1.content this change should be propagated to the other button (two way binding).
At the moment my button1.xaml looks like this:
<Grid x:Name="LayoutRoot">
<Button x:Name="x_button1" Margin="0,0,0,0" Content="{Binding ElementName=x_button2, Path=Content}" ClickMode="Press" Click="button1_Click"/>
</Grid>
But everthing that i get out of that is a button with no content at all, it is just blank as the binding silently fails.
How could I create the databinding in the context I described? Preferably in code and not XAML ;)
Thanks in advance
The chunk of documentation you need to read is this: XAML Namescopes
Your button1 xaml has a binding looking for an element with the name "x_button2". However in a real application there can be many controls which in turn have nested controls. All of these controls have all manner of UI elements some of which may have names.
It would be impossible to get anything done if all names throughout the entire application had be unique. Yet that would need to be true if it were for your button1 to be able to hunt down the existence of another control somewhere in the visual tree outside of that which it actually knows (its own xaml).
Hence each loaded Xaml document exists in its own "namescope" and the search for other elements with other names is limited to that "namescope".
The are various solutions to this problem depending on what you real requirements are as opposed to the simplified problem in your question.
Typically you give each of your controls a DependencyProperty to which the inner button Content property binds. In "MapLayer" as call it, could then bind the propert on one of your button controls to the other.

Cannot see named Silverlight control in code

In my first few hours with Silverlight 3, as an avid WPF user, I am greatly disappointed at the many things it doesn't support. This seems like an odd issue to me and it's so generic that I cannot find anything online about it.
I have the following XAML:
<controls:TabControl x:Name="workspacesTabControl" Grid.Row="1"
Background="AntiqueWhite" ItemsSource="{Binding Workspaces, ElementName=_root}"/>
However, I cannot see the workspacesTabControl in code-behind. I thought maybe IntelliSense is just being mean and tried to go ahead and compile it anyway, but got an error:
Error 1 The name 'workspacesTabControl' does not exist in the current context
How do I access controls in code-behind?
EDIT: I realized I've pasted the wrong error - I have two controls inside the UserControl called workspacesTabControl and menuStrip. I cannot get to either one of them by their name in the code-behind.
Just in case, here is the XAML for the menuStrip:
<controls:TreeView Grid.ColumnSpan="2" Height="100" x:Name="menuStrip"
ItemContainerStyle="{StaticResource MenuStripStyle}"
ItemsSource="{Binding Menu, ElementName=_root}"/>
EDIT AGAIN:
I'm not sure if this is helpful, but I've taken a look at the InitializeComponent() code and here's what I saw:
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
public void InitializeComponent() {
if (_contentLoaded) {
return;
}
_contentLoaded = true;
System.Windows.Application.LoadComponent(this, new System.Uri("/SapphireApplication;component/SapphireMain.xaml", System.UriKind.Relative));
}
It seems that it simply loads the XAML when it runs (not before or during compilation) so the menuStrip and workspacesTabControl names don't actually get registered anywhere (as they usually are in WPF/win Forms). Could that attribute be a problem? And where do I get rid of this requirement for all the future UserControls I make?
Check the properties in VS for the xaml file itself... make sure the Build Action is set to Page.
As ridiculous as it may sound, I have resorted to using FindName() method to access named items in code-behind:
this.FindName("workspacesTabControl") as TabControl
I realize that this is a ridiculous way but I am forced to use this for now. Please let me know if someone else has encountered this problem and have come up with a better solution!
When you first create a control, Visual Studio does not pick it up with intellisense. However, after you try to build the project, it should become availble. You can also just type the name in without intellisense and then build it. Haven't verified this, but I heard this was on the list of things to fix in SL4.
That being said, if you name a control inside of a datatemplate, that control is not directly accessible in code-behind. This is the same for WPF, though.
You should be able to see it in the codebehind, that part works the same as WPF, maybe if you fix the problem with the menuStrip, then visual studio will be able to build the xaml paty of the page and ull be able to access the tabcontrol
I've seen the same problem in my Silverlight development. Specific to my problem my named controls were nested inside other controls (i.e. a datagrid) and I was unable to access them in my code behind. Any named controls at the same nesting level or above the previously mentioned datagrid worked fine but anything inside it was lost into the abyss.
As already mentioned, it should just appear in Intellisense, however the fact that you're getting an error related to something else, i.e. "menuStrip" is probably interfering with Intellisense. Resolve that error and you'l probably find that you can access the "workspacesTabControl" control.
Are you possibly using some sample code or something where they've named a control "menuStrip" and you've renamed it?
Good luck
Check that you don't have any controls using the same class name as a namespace name. For example:
namespace Solution.ProjectName.workspacesTabControl
{
public class workspacesTabControl
{
...
}
}
This will also give you this error.
Good luck,
Mark

Resources