I Create a user control in "MyControl.xaml" like this:
<TreeView x:name="treeView" Grid.Row="0"/>
<!-- Rest of doc -->
and the user control get hosted in MainWindow.xaml:
...
...
Now how can I access the object treeView in the xaml behind code in MainWindow.xaml.cs?
I Tried this but failed.
MyControl.treeView.Items.Add(item); // object item created somewhere.
I Got the Error:
Error 1 An object reference is required for the non-static field, method, or property 'MyNameSpace.MyControl.treeView
What am I supposed to do about this?
I have created a Usercontrol with name "UC" as below
<Grid>
<StackPanel>
<TextBlock>Child</TextBlock>
<TreeView x:Name="treeView"/>
</StackPanel>
</Grid>
Added the control to its host
<Grid>
<local:UC x:Name="MyUC" />
</Grid>
And in code behind I can access it like...
MyUC.treeView.Items.Add("Item");
Please check your implementation
Related
Knowing a HierarchicalDataTemplate is defined somewhere in the resource tree (i.e. it could be defined at the app level, in a style, in the window's resources or somewhere in the hierarchy of controls on that window), programmatically, how can you determine which HierarchicalDataTemplate will be applied for a particular data type relative to a specific control?
For instance, in the following example, given that we have an object of type Foo, how can we get the HierarchicalDataTemplate for it--which happens to be defined at the window level here--relative to MainTreeView?
<Window ... >
<Window.Resources>
<HierarchicalDataTemplate DataType="{x:Type Foo}"
ItemsSource="{Binding Children}">
<TextBlock Text={Binding Name}" />
</HierarchicalDataTemplate>
</Window.Resources>
<TreeView x:Name="MainTreeView" />
</Window>
I've tried the following but it returns null:
var hdt = (HierarchicalDataTemplate)MainTreeView.FindResource(typeof(Foo));
Found it. DataTemplate objects don't use DataType for their default key like Style objects do. Instead, they use a DataTemplateKey object which you get as follows...
var dataTemplateKey = new DataTemplateKey(dataItem.GetType());
var hdt = (HierarchicalDataTemplate)MainTreeView.TryFindResource(dataTemplateKey);
That worked! :)
I created WPF UserControl which enables to enter some information now I have Main entry form where I want to use tow instances of that UserControl When I add my YserControl as Resource and than try to use it as ContrntControl's Content exception is thrown informing that control is already a logical child. Can anyone provide with sollution?
You can use the x:Shared attribute so that whenever something references the resource, a new instance is created instead of it being shared.
Thus you might have something like this:
<Window.Resources>
<MyUserControl x:Key="MyControlKey" x:Shared="False" .... />
....
</Window.Resources>
http://msdn.microsoft.com/en-us/library/aa970778.aspx
http://www.wpfmentor.com/2009/01/how-to-ensure-new-instance-of-resource.html
I just found out way to not throw exception but I want to know if this is right sollution
<TaicoControl:WizardPage Title="Title1"
BackButtonVisibility="Collapsed"
CancelButtonVisibility="Collapsed"
Description="Desctiption1"
PageType="Interior">
<ContentPresenter ContentTemplate="{StaticResource PersonEntryFormTemplate}" DataContext="{Binding Person}" />
</TaicoControl:WizardPage>
<TaicoControl:WizardPage Title="Title2"
BackButtonVisibility="Collapsed"
CancelButtonVisibility="Collapsed"
Description="Description2"
NextButtonVisibility="Collapsed"
PageType="Interior">
<ContentPresenter ContentTemplate="{StaticResource PersonEntryFormTemplate}" DataContext="{Binding Person.ContactPerson}" />
</TaicoControl:WizardPage>
Sorry, I'm thrashing around a bit learning MVVM, WPF, and XAML simultaneously.
I have a problem that I created and I am completely confused with how this should be handled in MVVM.
What I have is a parent window that contains a user control that draws graphs. The graph drawing XAML used to be part of the parent window, but I moved it to a user control for organization as the parent window was very big.
In the parent windows XAML I have .....
<Window ....>
<Window.Resources>
<ViewModel:DropGraphViewModel x:Key="myViewModel"/>
</Window.Resources>
<!-- Set the data context to the view model. -->
<Window.DataContext>
<Binding Source="{StaticResource myViewModel}"/>
</Window.DataContext>
.....
</Window>
And then in the new user control XAML class I have a resource that is created that is a 'generator' class that serves up things that will be used by parts of the graph. It looks like this...
<UserControl ......
<!-- Graph resources -->
<Grid.Resources>
<!-- The binding here for ItemsSource represents the collection the graph will be bound to -->
<!-- THIS LINE DOESN'T WORK ANYMORE -->
<Graphs:LineChartGenerator x:Key="generator" ItemsSource="{Binding Source={StaticResource myViewModel}, Path=SampleData}" Width="500" Height="200"> -->
</Grid.Resources>
And then later on when I want to do some things like draw graph lines I used to reference the generator through binding.
<!-- Connect the points -->
<Polyline Points="{Binding Source={StaticResource generator}, Path=Points}" Stroke="Blue" />
What is now broken now that I am in am using a nested user control is that when I create the instance of the 'generator' class in the resources, I can't pass in the binding that was ItemsSource="{Binding Source={StaticResource myViewModel}, Path=SampleData}" because I no longer have access to the view model (myViewModel) that is in the static resource of the parent window! So I can't set the binding during the creation time of the resource like I used to do.
What is the proper MVVM way to handle this type of pattern?
How do I inject the ItemsSource into my new user control so that it can pass it in when it creates the LineChartGenerator class instance?
DataContext is an inheritable DependencyProperty which means it trickles down the visual hierarchy.
Resources are not part of visual tree until they are hosted.
So in your case, your Graphs:LineChartGenerator has to be hosted in your UserControl and not delcared in the Resource section. Once you do that it acquires its own DataContext from the parent Window, this way as #GazTheDestroyer, pointed out you only need a implicit binding ItemsSource="{Binding SampleData}"
Since you are setting your ViewModel to be the DataContext of the outer Window, it will also be the DataContext of your UserControl, so you should be able to access it with a simple:
<Graphs:LineChartGenerator x:Key="generator" ItemsSource="{Binding SampleData}" Width="500" Height="200">
I have a XAML code that should load my UserControl inside the TabControl.
If I put this XAML code:
<DataTemplate x:Key="WorkspacesTemplate">
<TabControl
IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding Path=Gui}"
ItemTemplate="{StaticResource ClosableTabItemTemplate}"
Margin="4"
/>
</DataTemplate>
I have absolutly nothing appear in the windows (Gui property is inside the ViewModel class and return a UserControl).
But if I put his XAML code instead of the previous one:
<DataTemplate x:Key="WorkspacesTemplate">
<TabControl
IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding}"
ItemTemplate="{StaticResource ClosableTabItemTemplate}"
Margin="4"
/>
</DataTemplate>
I have the ViewModel Object loading:
(source: clip2net.com)
Here is a piece of code of the TextBoxInputViewModel that has the property Gui that should be binded to be able to get the Visual (usercontrol):
private UserControl gui;
public UserControl Gui
{
get
{
if (this.gui == null)
{
this.gui = new SimpleTextBoxInputControl();//Xaml User Control
this.gui.DataContext = this;//Bind the Visual and ViewModel
}
return this.gui;
}
}
Any idea how that I can get the UserControl instead of this object reference text?
The problem is that ItemSource is a collection, where as you're binding it to a property that is just one value. The error in the Output window that you're seeing is likely related to this.
Instead of returning a UserControl directly from your View Model, it would be better to return another View Model that represents the contents of the tab, and use templates to display that content. If you need it to be more dynamic than choosing the template based on the Type of the View Model, look into setting TabControl.ContentTemplateSelector. This needs to be set to a class that derives from DataTemplateSelector. You can use this class to decide which template to load based on the object bound to that tab.
you should create a template for your viewmodel in your app.xaml file like this
<DataTemplate DataType="{x:Type simpleModel:TextBoxInputViewModel}">
<myView:TextBoxInputControl />
</DataTemplate>
where simpleModel is the namespace of TextBoxInputViewModel, and TextBoxInputControl is the user control you want to show and myView is the namespace of that user control.
I have the following code and basically what i am not able to figure out is how to clone the whole grid and make a blank copy of them side by side.... for a clear understanding this is something to do with hospital application and the grid is related to a pregnancy so when said 'ADD CHILD' button a whole new grid should be created during run time, thanks for the help below is a link that might help people cause i tried it but not sure how to display it
How can you clone a WPF object?
You should put the object you are want to "clone" in a DataTemplate and reference this template from an ItemsControl, then when you need another grid add another item to the items control (or even better to the list the control is bound to) and the ItemsControl will create a new grid and bind it the new object.
For an example take a look at this post on my blog.
Here is an example for this application (I left only the relevant parts and I didn't test it, so there are probably some typos there):
<Window ... >
<Window.Resources>
<DataTemplate x:Key="ChildTemplate">
<Grid>
...
<TextBlock Text="Delivery Date:" Grid.Column="0" Grid.Row="0"/>
<TextBox Text="{Binding DeliveryDate}" Grid.Column="1" Grid.Row="0"/>
<TextBlock Text="Delivery Time:" Grid.Column="0" Grid.Row="1"/>
<TextBox Text="{Binding DeliveryTime}" Grid.Column="1" Grid.Row="1"/>
...
</Grid>
</DataTemplate>
</Window.Resources>
...
<Button Content="AddChild" Click="AddChildClick"/>
...
<ScrollViewer>
<ItemsControl ItemsSource="{Binding AllChildren}" ItemsTemplate="{StaticResource ChildTemplate}">
<ItemsControl.PanelTemplate>
<ItemsPanelTemplate><StackPanel Orientation="Horizontal"/></ItemPanelTemplate>
<ItemsControl.PanelTemplate>
</ScrollViewer>
...
</Window>
And in cs:
Set an object with all the form data as the Window's DataContext. I'll call this class PostDelveryData.
Create another class with the repeating data. I'll call it ChildDeliveryData.
Add a property of type ObservableCollection<ChildDeliveryData> called AllChildren to PostDeliveryData; it's important it'll be ObservableCollection and not any other type of collection.
Now, for the magic:
private void AddChildClick(object sender, RoutedEvetnArgs e)
{
((PostDeliveryData)DataContext).AllChildren.Add(new ChildDeliveryData());
}
And when you add the new item to the list another copy of the entire data template will be added.
I'm not sure that you're using the correct approach here. I would approach the problem by creating a "ChildGridControl" with a Child property, and let the Child property handle the databinding. Adding a new child to the GUI would involve creating a new instance of the ChildGridControl.
If I am understanding correctly, you should create a UserControl, which wraps your Grid and subsequent controls inside. And use this User control anywhere you wanted to replicate that UI.