Reputation: 466
I am not using the mvvm-pattern. I directly bind my UI to a model.
My problem is that the binding to the model-properties works. The textbox gets a red border if the model-property MyStringValue is invalid and the MyBoolValue-property also changes. But my button doesn't update the IsEnabled-property.
My XAML looks like that
<Window x:Class="OkButtonTest.MainWindow"
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"
xmlns:local="clr-namespace:OkButtonTest"
mc:Ignorable="d"
Title="MainWindow">
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<TextBox Grid.Row="0" Text="{Binding MyStringValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
<Button x:Name="MyExampleButton" Grid.Row="1" IsEnabled="{Binding MyBoolValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" Click="Button_Click" />
</Grid>
</Window>
The DataContext is bound to the model at the csharp-code:
using System.Windows;
namespace OkButtonTest
{
public partial class MainWindow : Window
{
ModelExample modelExample = new ModelExample();
public MainWindow()
{
InitializeComponent();
DataContext = modelExample;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("Button was clicked");
}
}
}
Notice that i have implemented Fody.PropertyChanged in my model, so i dont need to implement PropertyChanged for each property.
using System;
using System.ComponentModel;
namespace OkButtonTest
{
public class ModelExample : INotifyPropertyChanged, IDataErrorInfo
{
public event PropertyChangedEventHandler PropertyChanged;
private string myStringValue = "";
public string MyStringValue
{
get
{
return myStringValue;
}
set
{
myStringValue = value;
}
}
private bool myBoolValue;
public bool MyBoolValue
{
get
{
return myBoolValue;
}
set
{
myBoolValue = value;
Console.WriteLine($"MyBoolValue is {MyBoolValue.ToString()}");
}
}
public string Error
{
get
{
if(MyStringValue.Length < 5)
{
MyBoolValue = false;
return "Invalid string value";
}
MyBoolValue = true;
return string.Empty;
}
}
public string this[string columnName]
{
get
{
return Error;
}
}
}
}
Why doesnt my button update?
Upvotes: 1
Views: 1148
Reputation: 169200
Only return a string
from the Error
property and set the MyBoolValue
property in the setter of MyStringValue
:
public class ModelExample : INotifyPropertyChanged, IDataErrorInfo
{
public event PropertyChangedEventHandler PropertyChanged;
private string myStringValue = "";
public string MyStringValue
{
get
{
return myStringValue;
}
set
{
myStringValue = value;
MyBoolValue = !string.IsNullOrEmpty(myStringValue) && myStringValue.Length > 4;
}
}
private bool myBoolValue;
public bool MyBoolValue
{
get
{
return myBoolValue;
}
set
{
myBoolValue = value;
}
}
public string Error
{
get
{
if (MyStringValue.Length < 5)
{
return "Invalid string value";
}
return string.Empty;
}
}
public string this[string columnName]
{
get
{
return Error;
}
}
}
A getter shouldn't set anything. Your current approach of setting the MyBoolValue
in the getter of the Error
property results in a StackoverflowExcpetion
being thrown when I run it.
Upvotes: 1
Reputation: 5121
Seems you should be using following syntax to allow fody preprocess your viewmodel getters and setters.
[AddINotifyPropertyChangedInterface]
public class ModelExample : IDataErrorInfo
{
...
}
Also make sure you have this in your FodyWeavers.xml
<?xml version="1.0" encoding="utf-8" ?>
<Weavers>
<PropertyChanged/>
</Weavers>
Upvotes: 1