I'm doing something similar to this : https://www.wpf-tutorial.com/data-binding/using-the-datacontext/.I write this.DataContext = this;
in the cs file after the InitialieComponents(), and in the cs.xaml file I write Command = "{Binding BackCommand}" for a button.
But the resharper gives me an error: Cannot resolve symbol ”BackCommand“ due to unknown DataContext and the binding does not work.
Only If I do something like this it works: Command = "{Binding BackCommand, elementName = root}" and set the Name of the root xml(My class) to "root".
I dont understand why and how to fix this.. (Since I have seen instances where it worked just fine like in the url)
Thank you
You could add a DesignerDataContext to your XAML like:
<Window ...
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type=local:MyWindow, IsDesignTimeCreatable=False}"
>
This makes tools aware of the type of the DataContext.
Side note: I would recommend using the MVVM pattern and using a separate ViewModel class as DataContext.
Related
I would like to bind a list box to an observable collection in code behind. This is what I am using for the binding:
Binding binding = new Binding();
binding.Source = symTable;
substanceList.SetBinding(ListBox.ItemsSourceProperty, binding);
symTable inherits from ObservableCollection, the Count property gets updated appropriatelly so I know I am adding elements correctly, but the list box isn't. I didn't know what to set the path to, since in XAML it is bound to the whole list.
Note: When adding individual items to the ListBox they get shown, so it is not a display issue. I also tried:
this.Resources.Add("symTable", symTable);
in the window constructor and then this:
but it says the resource cannot be resolved.
I also tried adding it as a resource in XAML but it didn't work again:
//in the window's resources.
<s:SymbolTable x:Key="symTable"/>
...
<ListBox x:Name="substanceList" ItemsSource="{Binding Source={StaticResource symTable}}"/>
and then in code behind:
symTable = (SymbolTable)this.FindResource("symTable");
Does anyone know any other way to do this in code behind or XAML, I think the ElementName refers to objects defined in code behind.
Here is part of the class definition for symTable:
public class SymbolTable : ObservableCollection<Substance>
{
Dictionary<string, Substance> symbolTable;
...
public Substance Insert(Substance s)
{
if (!symbolTable.ContainsKey(s.Name))
{
symbolTable.Add(s.Name, s);
Items.Add(s);
}
return symbolTable[s.Name];
}
Note alright so I just noticed the most weird thing, Items.Add wasn't raising the INotifyChanged event. I used Items.Add in my Insert method, I am guessing that Items.Add doesn't raise a INotifyChanged event so the ListBox wasn't getting updated, but when did Add instead of Items.Add then it worked. Do you know if this is indeed the case?
Ok, following the comments on your question, here is how to declare SymbolTable as resource in XAML and how to bind a ListBox to it. Note the XAML namespace declaration 'local', which refers to the local namespace/assembly, which is named ListBindingTest in my test project.
<Window x:Class="ListBindingTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ListBindingTest"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:SymbolTable x:Key="symTable"/>
</Window.Resources>
<Grid>
<ListBox ItemsSource="{Binding Source={StaticResource symTable}}"/>
</Grid>
</Window>
You may access the SymbolTable resource in code behind in your window class like this:
SymbolTable st = (SymbolTable)Resources["symTable"];
st.Add(new Substance());
The DisplayMemberPath needs to be a public property of symTable.
You could always just set the ItemSource directly on the listbox.
substanceList.ItemsSource = symTable;
Just starting out using WPF / MVVM and have a question regarding using a viewmodel as the datacontext for a wpf window.
I'm using a view first approach and my view looks like this;
<Window x:Class="TestContext.TestForm"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="TestForm" Height="300" Width="300"
DataContext="{StaticResource testViewModel}">
<Grid>
<TextBox Text="{Binding Path=Address}" Height="23" HorizontalAlignment="Left" Margin="34,44,0,0" Name="textBox1" VerticalAlignment="Top" Width="120" />
</Grid>
</Window>
and I create my viewmodel in code like this ;
public class ViewModelFactory
{
public TestViewModel CreateTestViewModel()
{
return new TestViewModel();
}
}
I'm using the following approach in the app.xaml to create an instance of the viewmodel whenever I instantiate the view ;
<ObjectDataProvider x:Key="testViewModel" ObjectInstance="{StaticResource viewModelFactory}" MethodName="CreateTestViewModel">
This all works fine.
The problem is that I only ever see the viewmodel being created once. So new instances of the view use the same instance of the viewmodel.
I'd like to start out with a new instance of the viewmodel.
If I create the view model manually in the forms constructer ;
public TestForm()
{
InitializeComponent();
this.DataContext = new TestViewModel();
}
then it works as expected.
I'm trying to get my head around what's happening here...
Thanks....
Honestly using ObjectDataProvider isnt a good idea to get view models as that instance is single per App.
But if you insist to recreate the viewmodels you will have to refresh the testViewModel.
The way you do that is testViewModel.Refresh();
In Code
Create your view
Create Single Property on View (called VM)
Create your viewmodel
Assign the new viewmodel to VM
Set DataContext to ViewModel
Setup your bindings in XAML to point to the correct properties on your view model
As a rule
I never use ObjectDataProviders or instantiate anything in XAML (too buggy)
Always use the MVVM pattern
Be careful of static resources - they are only set once per app instance where dynamic resources can be updated
Yes, Agree with #AngelWPF You should use set DataContext as
View.DataContext = ViewModel;
You could instantiate you view model in the resources section of your view. Once you create new view - you'll get new view model.
Moreover, you'll get static bindings which are a bit performant and convenient to use because you'll get intellsense.
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:WpfApplication1="clr-namespace:WpfApplication1"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<WpfApplication1:MyViewModel x:Key="ViewModel"/>
</Window.Resources>
<Grid DataContext="{StaticResource ViewModel}">
<ItemsControl ItemsSource="{Binding Data}"/>
</Grid>
</Window>
I have a very simple user control, and I'm trying to instantiate it in XAML. I find that when I go a bit overzealous with the namespacing, I run into problems with x:Name.
Here is my UserControl:
<UserControl x:Class="UserControlTest.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="300" Height="300">
<Grid>
<Label Name="Label1">Label</Label>
</Grid>
</UserControl>
Here is the code-behind for the UserControl:
Namespace UserControlTest
Partial Public Class UserControl1
End Class
End Namespace
Now, note that I have the root namespace of my VB.Net project set to "UserControlTest". Knowing that, have a look at my main window:
Here is my main window:
<Window x:Class="Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:control="clr-namespace:UserControlTest.UserControlTest"
Title="Window1" Height="300" Width="300">
<Grid>
<control:UserControl1 />
</Grid>
</Window>
See how the control alias needs to have "UserControlTest.UserControlTest"? That's because I have the root namespace of my project set to UserControlTest, and I have defined the namespace of the UserControl to be UserControlTest, also. If I don't use a namespace for the UserControl, I don't have any troubles.
However, because I have done this, the build fails should I try to apply an x:Name to the UserControl, as follows:
<control:UserControl1 x:Name="test"/>
That will fail the build, with this error:
Type 'UserControlTest.UserControlTest.UserControl1' is not defined.
Can anybody explain why? Do I need to avoid putting my UserControls into namespaces just so I can give them x:Name values? I'd like to manipulate my UserControls from code-behind, and without an x:Name, I'm up the creek. But I don't want to sacrifice namespace usage just to get it!
Thanks very much.
I had the same problem (after rebuilding the project, first it worked fine...). I put UserControl into separate namespace.
What is the namespace defined as in the code-behind of your user control?
If your project was called Foo and you had a folder called Controls inside that project, any new user control added to that folder would be given the namespace Foo.Controls.
Then in your XAML you can reference it like so:
xmlns:Controls="clr-namespace:Foo.Controls"
...
<Controls:UserControl1 x:Name="uc1"/>
It seems like you have a naming issue.
EDIT:
Here's how I'm doing it in a project of mine.
StatusBar.xaml.cs
namespace Client.Controls.UserControls
{
public partial class StatusBar : UserControl
{
...
}
}
StatusBar.xaml
<UserControl x:Class="Client.Controls.UserControls.StatusBar">
</UserControl>
Main.xaml.cs
using Client.Controls.UserControls;
namespace Client
{
public partial class Main : Window
{
...
}
}
Main.xaml
<Window x:Class="Client.Main"
xmlns:UserControls="clr-namespace:Client.Controls.UserControls">
<UserControls:StatusBar x:Name="mainStatusBar" />
</Window>
I encountered the same problem in a vb.net project, and despite trying the suggestions here and elsewhere, could not solve the issue. In fact, I was able to take the exact same code out of our project to a new project, and it worked just fine (as far as I could determine all the configuration in the new project was identical). In the solution provided by David, I notice he is using c# - I am wondering if this is some weirdness associated with vb.net.
In the end, the user control I needed to use was quite simple and I implemented it as a resource ControlTemplate to get around the issue. Sorry I don't have a better answer, I am really not happy wih my findings...
I created a UserControl in WPF:
In Xaml:
<UserControl x:Class="OutlookPanel.MailRelation"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="300" Width="300"
xmlns:graph="clr-namespace:MyPanel"
>
<DockPanel>
<graph:Graph Name="theGraph" NodesBindingPath="ChildNodes"
NodeTemplateSelector="{StaticResource nodeTemplateSelector}">
..
</DockPanel>
</UserControl>
I cs:
object theThing = e.Parameter;
((MailRelation)sender).theGraph.CenterObject = theThing;
This last sentence does not work as theGraph is not accessible.
Any idea why i can access theGraph ?
Thanks
John
Name="theGraph"
should be
x:Name="theGraph"
from http://msdn.microsoft.com/en-us/library/ms752059.aspx
x:Name: Specifies a run-time object
name for the instance that exists in
run-time code after an object element
is processed. You use x:Name for cases
of naming elements where the
equivalent WPF framework-level Name
property is not supported. This
happens in certain animation
scenarios.
Probably because that property is private. Provide a public getter and you should be able to get it. In your code, add something like
public Graph TheGraph { get { return theGraph; } }
I'm trying to bind the Forderground dependency property to my UIControl, so that it's drawn in the color the user wishes. Since myUiControl.Foderground autocopletes, I thought I could just bind it in the XAML file like this:
{Binding ElementName=rootControl, Path=Forderground}
When debugging VS says it cannot find the source for binding with this DependencyProperty.. but I couldn't figure out why this is.
Also how can I list all dependency properties of an object while debugging?
UPDATE: If below wasn't enough for you, try downloading this sample and looking at it.
The ElementName needs to be set as the "x:Name" of your root control and the Path needs to be set to the Property on the root element you wish to bind to. Without the name it cannot find the element you are referring to (hence the initial error) and without the Path it doesn't bind to the correct property (check your output at runtime for an error).
Try this:
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid x:Name="root" Background="Green">
<Button Background="White" Margin="100">
<TextBlock Background="{Binding ElementName=root, Path=Background}" Text="TESTING TESTING"/>
</Button>
</Grid>
Can you confirm that your "rootControl" element is defined earlier in the xaml markup than your Binding holder? Usually the Bindings are bound to the earlier declared elements.
If you mean ImmediateWindow and IntelliSense usage while debugging than each dependency property metadata has usually public static access modifiers. You can for instance type "Control." and observe all the corresponding dependency properties, routed events and attached properties members.
Hope this helps.