Binding text to my textblock isn't working - c#

Here's the xaml:
<TextBlock Text="{Binding Errors}" Grid.Row="3" Foreground="Red"/>
Here's the ViewModel code:
private string _errors = "";
public string Errors
{
get { return this._errors; }
set
{
if(_errors != value)
{
_errors = value;
RaisePropertyChanged(() => Errors);
}
}
}
and then in some function I change the _errors variable
_errors = "Compiler Errors :\r\n";
But nothing happens in the TextBlock. What am I doing wrong?

You are setting _errors variable directly - so no RaisePropertyChanged fired. Try to set value by
Errors = = "Compiler Errors :\r\n";

private string _errors = "";
public string Errors
{
get { return this._errors; }
set
{
if(_errors != value)
{
_errors = value;
RaisePropertyChanged("Errors");
}
}
}
set it like this :
Errors = "..."
I don't know how works the method RaisePropertyChanged, but if the lambda expression ()=>Errors is executed it will return the string contained in _errors and not the name of the property that changed ? So try to give directly the name of the property if the method exists.

Related

How can I use an array in a ViewModel?

My code looks like this right now with two lines of code for each message. The code works but if I have for example 30 messages that I can each give values to then I will need to have 60 lines of code just to declare everything:
string _msg1;
string _msg2;
public string Msg1 { get => _msg1; set => SetProperty(ref _msg1, value); }
public string Msg2 { get => _msg2; set => SetProperty(ref _msg2, value); }
and in C# I assign to these:
vm.Msg1 = "A";
vm.Msg2 = "B";
and in the XAML I bind my Text to Msg1 and another Text to Msg2
Can someone tell me how / if I can do this with array so that I would assign like this and hopefully so the assignment of the array can just be done in two lines instead of 2 lines for every single message:
vm.Msg[0] = "A";
vm.Msg[1] = "B";
For reference:
public class ObservableObject : INotifyPropertyChanged
{
protected virtual bool SetProperty<T>(
ref T backingStore, T value,
[CallerMemberName]string propertyName = "",
Action onChanged = null)
{
if (EqualityComparer<T>.Default.Equals(backingStore, value))
return false;
backingStore = value;
onChanged?.Invoke();
OnPropertyChanged(propertyName);
return true;
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName]string propertyName = "") =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
You can create a simple wrapper class with indexing that supports property change notification.
For example:
public class Messages : ObservableObject
{
readonly IDictionary<int, string> _messages = new Dictionary<int, string>();
[IndexerName("Item")] //not exactly needed as this is the default
public string this[int index]
{
get
{
if (_messages.ContainsKey(index))
return _messages[index];
//Uncomment this if you want exceptions for bad indexes
//#if DEBUG
// throw new IndexOutOfRangeException();
//#else
return null; //RELEASE: don't throw exception
//#endif
}
set
{
_messages[index] = value;
OnPropertyChanged("Item[" + index + "]");
}
}
}
And, create a property in view model as:
private Messages _msg;
public Messages Msg
{
get { return _msg ?? (_msg = new Messages()); }
set { SetProperty(ref _msg, value); }
}
Now you can set or update values as:
vm.Msg[0] = "A";
vm.Msg[1] = "B";
Bindings in XAML will be same as:
<Label Text="{Binding Msg[0]}" />
<Label Text="{Binding Msg[1]}" />
Sample usage code
XAML
<StackLayout Margin="20">
<Label Text="{Binding Msg[0]}" />
<Label Text="{Binding Msg[1]}" />
<Label Text="{Binding Msg[2]}" />
<Label Text="{Binding Msg[3]}" />
<Label Text="{Binding Msg[4]}" />
<Button Text="Trigger update" Command="{Binding UpdateMessage}" />
</StackLayout>
Code-behind, view-model
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
var viewModel = new MainViewModel();
viewModel.Msg[0] = "Original message 1";
viewModel.Msg[1] = "Original message 2";
viewModel.Msg[2] = "Original message 3";
viewModel.Msg[3] = "Original message 4";
viewModel.Msg[4] = "Original message 5";
BindingContext = viewModel;
}
}
public class MainViewModel : ObservableObject
{
private Messages _msg;
public Messages Msg
{
get { return _msg ?? (_msg = new Messages()); }
set { SetProperty(ref _msg, value); }
}
public ICommand UpdateMessage => new Command(() =>
{
Msg[2] = "New message 3";
Msg[0] = "New message 1";
});
}
Arrays will not raise property changed event. You'll need to use an ObservableCollection that can raise an event when the collection has changed. However, this doesn't raise an event when the object inside the collection has changed it's value. You'll need to wrap your object, in this case a string, into a type that can raise property changed events.
Something like the following would work:
public class BindableValue<T> : INotifyPropertyChanged
{
private T _value;
public T Value
{ get => _value; set => SetProperty(ref _value, value); }
// INotifyPropertyChanged and SetProperty implementation goes here
}
private ObservableCollection<BindableValue<string>> _msg;
public ObservableCollection<BindableValue<string>> Msg
{ get => _msg; set => SetProperty(ref _msg1, value); }
you would be binding to Msg[0].Value, Msg[1].Value etc.,
Not entirely sure that I got the question, but as I understood the simplest way is this:
The Viewmodel:
Just bind to an ObservableCollection of strings, because it already implements INotifyCollectionChanged and INotifyPropertyChanged.
RelayCommand is just an implementation of ICommand and I'm assuming you have heard of them since you are doing WPF MVVM.
using System.Collections.ObjectModel;
namespace WpfApp1
{
public class MainWindowViewmodel
{
public ObservableCollection<string> Messages { get; set; }
public MainWindowViewmodel()
{
Messages = new ObservableCollection<string>();
Messages.Add("My message!");
ChangeMessageCommand = new RelayCommand(ChangeMessageExcecute);
}
public RelayCommand ChangeMessageCommand { get; set; }
private void ChangeMessageExcecute() => Messages[0] = "NEW message!";
}
}
The View:
In the view you can just bind your Textblocks to the Elements of the ObservableCollection. When you press the button, the Command gets called and changes the message in the window.
<Window x:Class="WpfApp1.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"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<StackPanel>
<TextBlock Text="{Binding Messages[0]}" HorizontalAlignment="Center"/>
<Button Content="Change Message" Command="{Binding ChangeMessageCommand}" Width="200"/>
</StackPanel>
</Grid>
</Window>
Kind regards,
misdirection
I Assume that your given example is running and working as expected (Atleast with 2 items)
View Code.
Assuming you want to show all the 30 messages as a list.
<ListView ItemsSource="{Binding MessagesArray}"/>
Also you should set the DataContext properly, Comment below if you need any help
View Model Code.
We are using an ObservableCollection instead of array. Since pure arrays doesn't support proper binding features.
private ObservableCollection<string> _messagesArray;
public ObservableCollection<string> MessagesArray
{
get { return _messagesArray; }
set { SetProperty(ref _messagesArray, value); }
}
Assigning Values
MessagesArray = new ObservableCollection<string>();
vm.MessagesArray.Add("A");
vm.MessagesArray.Add("B");
In the assignment code MessagesArray = new ObservableCollection<string>(); assigns a new object of ObservableCollection of String
If you are new to ObservableCollection think of this as an wrapper to string[], but not actually true
SetProperty method will tell the XAML View that a new collection is arrived, so the UI will rerender the list.
When you call vm.MessagesArray.Add("B"); internal logics inside the method Add will tell the XAML View a new item is added to the ObservableCollection so the view can rerender the ListView with the new item.
Update 27 October 2018
You can create your own array using any of the below ways. (Not all)
string[] dataArray = new string[30];
1. this will create an array with 30 null values
string[] dataArray = { "A", "B", "C" }; //Go up to 30 items
2. this will create an array with predefined set of values, you can go up to 30
string[] dataArray = Enumerable.Repeat<string>(String.Empty, 30).ToArray();
3. this will create an array with string which holds empty values, Instead of String.Empty you can put any string value.
Choose any of the above method
I recommend the last method, then you can assign that into a Observable Collection like below.
MessagesArray = new ObservableCollection<string>(dataArray);
Now the trick is
vm.MessagesArray[0] = "A"
vm.MessagesArray[25] = "Z"
View might look like below
<TextBlock Text="{Binding MessagesArray[0]}"/>
<TextBlock Text="{Binding MessagesArray[1]}"/>
What about using reflection?
You can ask for all the public properties of type string with name "Msg*".
For example:
static class Program
{
static void Main(string[] args)
{
var vm = new MessagesViewModel();
PropertyInfo[] myProperties = vm.GetType()
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(p => p.PropertyType == typeof(string) && p.Name.Contains("Msg"))
.ToArray();
foreach (var propertyInfo in myProperties)
{
//You can also access directly using the indexer --> myProperties[0]..
propertyInfo.SetValue(vm, $"This is {propertyInfo.Name} property");
}
Console.WriteLine(vm.Msg1);
Console.WriteLine(vm.Msg2);
}
}
public class MessagesViewModel
{
string _msg1;
string _msg2;
public string Msg1 { get => _msg1; set => _msg1 = value; }
public string Msg2 { get => _msg2; set => _msg2 = value; }
}
If this type of solution fits, you can wrap it with an indexer, sort the array to match the index and the Msg[num].

Binding Radio Button IsChecked to object's current array of element's state

I am developing a small utility using C#/WPF/MVVM which would allow to set the input state of a controller we are using for testing. The communication between the app I am developing and the hardware/our web service communication to the hardware is only one way, meaning that the app will only be able to set the state of the inputs, but not get the states.
Another point to mention is that some types are already defined for this in some other parts of our solution, which are all in F#. To do my app, I am currently using C#. So I did a Unit class to wrap around the LocalControllerTypes.LocalController type defined in F#, containing a lot of needed information.
In order to do that, I have an enum enumerating the InputState possible (currently there is Active or Normal, but that list could potentially grow with time). Also, the number of inputs present on each unit type is different (some have 2, some have 4, some have more), so I have an ItemControl binded on the selected unit's array of Inputs, which unfortunately only contains the Name of the input which I have to display. The unit has 2 other properties related to the inputs it has, InputWriters, which is an array of a type which is used to send the command to the hardware/web service communicating with that hardware, and InputStates, which is an array of InputState for each input it has, as last set in the app (since we can't get the state from the hardware).
Now I would like to bind the IsChecked property of the radio buttons (which is what I define as ItemTemplate of the ItemsControl) to the InputState of the currently SelectedUnit (in my ViewModel). The problem I am having, is that I would somehow need to know the radio button is for which index of the SelectedUnit's Inputs array, in order to get the item at the same index for the SelectedUnit's InputStates property.
Is there any way to achieve this?
MainWindow.xaml:
...
<ItemsControl Grid.Row="1" ItemsSource="{Binding SelectedUnit.LocalControllerInfo.Inputs}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Margin="10" FontSize="15" Style="{StaticResource TextBlockNormalBase}" Text="{Binding InputName}"/>
<StackPanel Orientation="Horizontal">
<RadioButton Margin="10" Foreground="White" Content="Normal"
IsChecked="{Binding Path=?,
Converter={StaticResource inputToBoolConverter},
ConverterParameter=?}"/>
<RadioButton Margin="10" Foreground="White" Content="Active"
IsChecked="{Binding Path=?,
Converter={StaticResource inputToBoolConverter},
ConverterParameter=?}"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
...
Unit.cs:
public class Unit : BindableObject
{
public enum InputState
{
Normal,
Active
}
private LocalControllerTypes.LocalController _localControllerInfo;
private LocalControllerTypes.ArduinoInjector[] _arduinoInjector;
private WebWriter.WebWriter[] _inputWriters;
private SNMPNetworkSwitchConnection.SNMPNetworkSwitchConnection _networkSwitchConnection;
private InputState[] _inputStates;
private bool _isUnitConnected;
public Unit(LocalControllerTypes.LocalController localControllerInfo,
LocalControllerTypes.ArduinoInjector[] arduinoInjector,
WebWriter.WebWriter[] inputWriters,
SNMPNetworkSwitchConnection.SNMPNetworkSwitchConnection networkSwitchConnection)
{
_localControllerInfo = localControllerInfo;
_arduinoInjector = arduinoInjector;
_inputWriters = inputWriters;
_networkSwitchConnection = networkSwitchConnection;
// This assumption might not always be true, but there is no way for now to get the input state
_inputStates = Enumerable.Repeat(InputState.Normal, _inputWriters.Length).ToArray();
// This assumption might not always be true, but there is no way for now to get the connection state
_isUnitConnected = true;
}
public LocalControllerTypes.LocalController LocalControllerInfo
{
get
{
return _localControllerInfo;
}
set
{
if (_localControllerInfo != value)
{
_localControllerInfo = value;
RaisePropertyChanged();
}
}
}
public LocalControllerTypes.ArduinoInjector[] ArduinoInjectors
{
get
{
return _arduinoInjector;
}
set
{
if (_arduinoInjector != value)
{
_arduinoInjector = value;
RaisePropertyChanged();
}
}
}
public WebWriter.WebWriter[] InputWriters
{
get
{
return _inputWriters;
}
set
{
if (_inputWriters != value)
{
_inputWriters = value;
RaisePropertyChanged();
}
}
}
public SNMPNetworkSwitchConnection.SNMPNetworkSwitchConnection NetworkSwitchConnection
{
get
{
return _networkSwitchConnection;
}
set
{
if (_networkSwitchConnection != value)
{
_networkSwitchConnection = value;
RaisePropertyChanged();
}
}
}
public InputState[] InputStates
{
get
{
return _inputStates;
}
set
{
if (_inputStates != value)
{
_inputStates = value;
RaisePropertyChanged();
}
}
}
public bool IsUnitConnected
{
get
{
return _isUnitConnected;
}
set
{
if (_isUnitConnected != value)
{
_isUnitConnected = value;
RaisePropertyChanged();
}
}
}
}
MainViewModel.cs:
public class MainViewModel : INotifyPropertyChanged
{
private Unit _selectedUnit;
private ObservableCollection<Unit> _units;
private string _reader1RawCardData;
private string _reader2RawCardData;
private int _reader1BitsCount;
private int _reader2BitsCount;
public event PropertyChangedEventHandler PropertyChanged;
public MainViewModel(IUnitStore unitStore)
{
UnitStore = unitStore;
// We could use directly the unitstore instead of creating another container and binding on that, but
// not doing so will allow us to add unit filtering further down the road
_units = new ObservableCollection<Unit>(unitStore.Units);
_selectedUnit = _units.First();
_reader1RawCardData = "";
_reader2RawCardData = "";
_reader1BitsCount = 0;
_reader2BitsCount = 0;
}
protected void RaisePropertyChanged([CallerMemberName]string propertName = "")
{
var temp = PropertyChanged;
if (temp != null)
{
temp(this, new PropertyChangedEventArgs(propertName));
}
}
protected void RefreshUnitStore(object obj)
{
UnitStore.UpdateStore();
Units = new ObservableCollection<Unit>(UnitStore.Units);
SelectedUnit = Units.First();
}
protected void SendReaderCardSwipe(object obj)
{
int unitReaderNumber = (int)obj;
IPAddress arduinoIp = SelectedUnit.LocalControllerInfo.Readers[unitReaderNumber - 1].InjectorIp;
int injectorNumber = SelectedUnit.LocalControllerInfo.Readers[unitReaderNumber - 1].InjectorNumber;
string serviceUrl = SelectedUnit.ArduinoInjectors.Where(injector => injector.Ip.Equals(arduinoIp)).First().Url;
InjectorInterface.CardSwipe<IPAddress>(serviceUrl, arduinoIp, injectorNumber, Reader1BitsCount, Reader1RawCardData);
}
protected void UpdateSelectedUnitConnectionState(object obj)
{
((INetworkConnection.INetworkConnection)SelectedUnit.NetworkSwitchConnection).SetConnection(SelectedUnit.IsUnitConnected);
}
public IUnitStore UnitStore
{
get;
private set;
}
public Unit SelectedUnit
{
get
{
return _selectedUnit;
}
set
{
if (_selectedUnit != value)
{
_selectedUnit = value;
RaisePropertyChanged();
}
}
}
public ObservableCollection<Unit> Units
{
get
{
return _units;
}
set
{
if (_units != value)
{
_units = value;
RaisePropertyChanged();
}
}
}
public string Reader1RawCardData
{
get
{
return _reader1RawCardData;
}
set
{
if (_reader1RawCardData != value)
{
_reader1RawCardData = value;
RaisePropertyChanged();
}
}
}
public string Reader2RawCardData
{
get
{
return _reader2RawCardData;
}
set
{
if (_reader2RawCardData != value)
{
_reader2RawCardData = value;
RaisePropertyChanged();
}
}
}
public int Reader1BitsCount
{
get
{
return _reader1BitsCount;
}
set
{
if (_reader1BitsCount != value)
{
_reader1BitsCount = value;
RaisePropertyChanged();
}
}
}
public int Reader2BitsCount
{
get
{
return _reader2BitsCount;
}
set
{
if (_reader2BitsCount != value)
{
_reader2BitsCount = value;
RaisePropertyChanged();
}
}
}
public ICommand RefreshSourceCommand
{
get
{
return new RelayCommand(RefreshUnitStore);
}
}
public ICommand SendReaderCardSwipeCommand
{
get
{
return new RelayCommand(SendReaderCardSwipe);
}
}
public ICommand UpdateSelectedUnitConnectionStateCommand
{
get
{
return new RelayCommand(UpdateSelectedUnitConnectionState);
}
}
}
Your ItemsControl is bound to SelectedUnit.LocalControllerInfo.Inputs. What is the type of .Inputs?
As written your bindings will not have access to InputState or InputName. That's not really in the scope of "how to identify what array item goes with what enum"
To address your original issue, one possibility would be to nest some tuples and bind to that, a la
List<Tuple<int,State>> States = new List<Tuple<int,State>>();
States.Add(new Tuple<int, State>(1,State.Bar));
States.Add(new Tuple<int, State>(2, State.Foo));
States.Add(new Tuple<int, State>(3, State.Bar));

Xamarin.Forms binding not updating the label ui

I want to bind my label to my model which works fine but the actual value of the property does not get updated, I also implemented INotifyPropertyChanged
Am I doing something wrong here?
My Model
public string ErgebnisBasisPaketPreisString {
get
{
return _ergebnisBasisPaketPreis = (BasisPaketPreis[(int) Basispaket] * (BasisPaketInterval + 1)).ToString("C0");
}
set
{
_ergebnisBasisPaketPreis = value;
OnPropertyChanged(nameof(ErgebnisBasisPaketPreisString));
}
}
My Label:
<Label x:Name="LabelPreisBasispaketIntervall"
Text="{Binding ErgebnisBasisPaketPreisString}"
Grid.Column="3"
VerticalOptions="Center"/>
And I am setting the binding context to my Content page.
ContentPage:
public partial class GeräteKonfiguration : ContentPage {
public GeräteKonfiguration(User currentUser) {
InitializeComponent();
_currentUser = currentUser;
Initialize();
}
private User _currentUser;
private Gerät _currentGerät;
private void Initialize() {
_currentGerät = _currentUser.ServiceModuleAngebotObj.CurrentGerät;
LabelPreisBasispaketIntervall.SetBinding(Label.TextProperty, _currentGerät.ErgebnisBasisPaketPreisString);
LabelPreisBasispaketIntervall.BindingContext = _currentGerät;
BindingContext = _currentGerät;
ToolBarView.BackButton.Clicked += BackButtonOnClicked;
ToolBarView.BackButton.Text = "blabla";
ToolBarView.TitleText = _currentGerät.Anwendung + " - " + _currentGerät.Antriebsart +
" - " + _currentGerät.Baureihe + " - " + _currentGerät.Typ;
LabelPreisBasispaketIntervall.Text = _currentGerät.ErgebnisBasisPaketPreisString;
}
}
This line in your code behind is overwriting your binding by binding the label text to whatever the value of the property is.
LabelPreisBasispaketIntervall.SetBinding(Label.TextProperty, _currentGerät.ErgebnisBasisPaketPreisString)
This isn't likely to be a valid binding path (which would be ErgebnisBasisPaketPreisString), so the binding won't work.
You then get the correct initial value by setting it here:
LabelPreisBasispaketIntervall.Text = _currentGerät.ErgebnisBasisPaketPreisString;
Remove both of these lines, and the binding should work - your XAML looks correct.
Secondly, your property getter doesn't use the value you set it to - you re-compute it each time. Your property should probably just be:
public string ErgebnisBasisPaketPreisString
{
get { return _ergebnisBasisPaketPreisString; }
set
{
_ergebnisBasisPaketPreisString = value;
OnPropertyChanged(nameof(ErgebnisBasisPaketPreisString));
}
}
And you can set the initial computed value in the constructor. Or stick to the computed property and raise the property changed in the dependent properties:
public string ErgebnisBasisPaketPreisString
{
get { return BasisPaketPreis[(int) Basispaket] * (BasisPaketInterval + 1)).ToString("C0"); }
}
public string Basispaket
{
get { return _basispaket; }
set
{
_basispaket = value;
OnPropertyChanged(nameof(Basispaket));
OnPropertyChanged(nameof(ErgebnisBasisPaketPreisString));
}
}
// and similar for the other properties that are used in the computation

Value Converter not working with caliburn.micro

I'm building a windows8.1 app and trying to tamper with the ConventionManager of caliburn.micro . I want to enable name convention binding with ValueConverters.
More specifically I have a collection of ProductViewModels that have two properties Value and IsValid. I want to bind the Value property to a textblock and the IsValid property to the BorderColorBrush of a Border via a ValueConverter.
Here's my code inside Configure in app.xaml.cs
var oldApplyConverterFunc = ConventionManager.ApplyValueConverter;
ConventionManager.ApplyValueConverter = (binding, bindableProperty, property) =>
{
if (bindableProperty == Control.BorderBrushProperty && typeof(bool).IsAssignableFrom(property.PropertyType))
// ^^^^^^^ ^^^^^^
// Property in XAML Property in view-model
binding.Converter = booleanToBrush;
// ^^^^^^^^^^^^^^^^^^^^^^^^^
// My converter used here. Code never reaches this point
// else I use the default converter
else if (bindableProperty == TextBlock.TextProperty && typeof(int).IsAssignableFrom(property.PropertyType))
{
//Code reaches this point when it should.
oldApplyConverterFunc(binding, bindableProperty, property);
}
else
{
oldApplyConverterFunc(binding, bindableProperty, property);
}
};
The problem is that the program never enters the first if clause. Does anybody know why???
My VM and xaml are these.
public class ProductViewModel
{
public ProductViewModel(int value)
{
_value = value;
}
private int _value;
public int Value
{
get { return _value; }
set
{
_value = value;
}
}
private bool _isValid;
public bool IsValid
{
get
{
_isValid = some validation logic;
return _isValid;
}
}
}
the view is a user control
<Border x:Name="IsValid">
<TextBlock x:Name="Value"/>
</Border>

How to do validation for a mandatory field without using Binding Path

The problem i have now is that,
For each textBox i have currently, i have to specify a Binding path in order to validate whether the textBox is empty or not.
However, if it so happens that i have a hundred textBox, i cant possibly create a get and set method for all 100 textBox individually. So is there any better way to do the current validation that i have now?
Below is the codes that i currently have,
In XAML
<Grid.BindingGroup>
<BindingGroup Name="RequiredFields">
<BindingGroup.ValidationRules>
<local:MandatoryFieldRule ValidationStep ="CommittedValue"/>
</BindingGroup.ValidationRules>
</BindingGroup>
</Grid.BindingGroup>
<TextBox x:Name="ds_instruct" HorizontalAlignment="Left" Height="30"
Margin="286,186,0,0" TextWrapping="Wrap" VerticalAlignment="Top"
Width="275" FontSize="11" GotFocus="textBox_Expand"
LostFocus="textBox_Expand" Tag="Default Special Instruction"
SpellCheck.IsEnabled="True"
Text="{Binding Path=Text, BindingGroupName=RequiredFields,ValidatesOnDataErrors=true}"/>
In validation file:
public String Text { get; set; }
public String Text1 { get; set; }
#region IDataErrorInfo Members
public string Error
{
get {throw new NotImplementedException(); }
}
public string this[string columnName]
{
get
{
string result = null;
if (columnName == "Text")
{
if (string.IsNullOrEmpty(Text))
{result = "Mandatory field required"; }
}
if (columnName == "Text1")
{
if (string.IsNullOrEmpty(Text1))
{ result = "Mandatory field required"; }
}
return result;
}
}
#endregion
So my question is, how to validate a mandatory field for multiple textBoxes without specifying a one to one binding(TextBox to a getter and setter method)?
Thank you all in advance!
Perhaps you could use Reflection to check the values of the string
public string this[string columnName]
{
get
{
string result = null;
if (string.IsNullOrEmpty(this.GetType().GetProperty(columnName).GetValue(this) as string))
{
result = "Mandatory field required";
}
return result;
}
}

Categories