Reputation: 2221
I use Wpf 4.5 and Caliburn Micro 2.0.2.
I want to bind a Textbox to a property of view model. The property (called ResultData) is an object from class TextXmlData. The class is a automatically generated class from a xsd. I use Microsoft Xsd.exe to make it.
This is the view model
public class ShellViewModel : PropertyChangedBase, IHaveDisplayName
{
public string DisplayName { get; set; }
private TestXmlData _resultData;
public TestXmlData ResultData
{
get { return _resultData; }
set
{
_resultData = value;
NotifyOfPropertyChange(() => _resultData);
}
}
public ShellViewModel()
{
DisplayName = "Shell Window";
}
public void CreateObject()
{
String xmlData = "<TestXmlData><Id>88</Id><Name>What a name</Name></TestXmlData>";
if (ResultData == null) { ResultData = new TestXmlData(); }
XmlSerializer oXmlSerializer = new XmlSerializer(ResultData.GetType());
ResultData = (TestXmlData)oXmlSerializer.Deserialize(new StringReader(xmlData));
// at this point the debugger shows that the ResultData is correctly filled,
// the Name is definitely not empty
}
}
and this is the view
<UserControl x:Class="CMWpfXmlSerializer2Ways.Views.ShellView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:DesignHeight="300"
d:DesignWidth="300"
mc:Ignorable="d">
<Grid Width="300" Height="300">
<StackPanel Width="200"
Height="100"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<Button x:Name="CreateObject"
Width="190"
Content="Create Object from XML" />
<TextBox Width="190"
DataContext="{Binding ResultData}"
Text="{Binding Name}" />
</StackPanel>
</Grid>
</UserControl>
and the TextBox shows always empty!
I have tried also with Text="{Binding ResultData.Name}", but the TextBox still shows empty.
Anyone can help and show me what is wrong with my code above? Please feel free to modify the code. Thanks in advance.
Upvotes: 1
Views: 3639
Reputation: 2221
after I read your comments, hints, suggestions and my code again and again, I find out the cause of the problem incidentally. And it is my own mistake (yes, my stupid mistake)
I have used the backing field _resultData on NotifyOfPropertyChange instead of the property name ResultData! (please see in the view model the setter of property ResultData)
Thank you very much to you all!
Upvotes: 0
Reputation: 3914
Do you have debugging enabled with Caliburn.MIcro? This would be done from your BootStrapper. This will tell us whether or not your view and viewmodel are bound correctly.
usually placed into the CTOR of the bootstrapper LogManager.GetLog = type => new DebugLog(type);
Since you are using a UserControl for your shellview I would like to see your BootStrapper.
I suspect a few things are incorrect or namespaces aren't set correctly, which would lead to binding errors.
Upvotes: 1
Reputation: 9827
ResultData is a property of ViewModel. So, you need to set ViewModel as DataContext at some higher level, then you can use it's property as binding source at some lower level.
To run your sample, I made some changes and ran like below :
<TextBox x:Name="tbName" DataContext="{Binding ResultData}" Text="{Binding Name}" />
///
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
ShellViewModel vm = new ShellViewModel();
vm.CreateObject();
this.DataContext = vm;
}
...
///
public class ShellViewModel : INotifyPropertyChanged
{
public string DisplayName { get; set; }
private TestXmlData _resultData;
public TestXmlData ResultData
{
get { return _resultData; }
set
{
_resultData = value;
OnPropertyChanged("ResultData");
}
}
public void OnPropertyChanged(string name)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
public ShellViewModel()
{
DisplayName = "Shell Window";
}
public void CreateObject()
{
String xmlData = "<TestXmlData><Id>88</Id><Name>What a name</Name></TestXmlData>";
if (ResultData == null) { ResultData = new TestXmlData(); }
XmlSerializer oXmlSerializer = new XmlSerializer(ResultData.GetType());
ResultData = (TestXmlData)oXmlSerializer.Deserialize(new StringReader(xmlData));
// at this point the debugger shows that the ResultData is correctly filled,
// the Name is definitely not empty
}
public event PropertyChangedEventHandler PropertyChanged;
}
Upvotes: 2