I searched a lot for the solution to this, but can't seem to figure it out. (Just saying, this will be a long post)
Preface: This is NOT MVVM
Problem: I have a progress bar. I am currently trying to bind a public double to it from within the xaml's .cs file. However, whenever I use value's bind function, it never works, resulting in iNotifyPropertyChanged not working, etc. etc....
The variable it is bound to serves the purpose of updating the progress bar value. The way that is completed is by setting the value in a separate for loop in another method/class. The value is set by a simple equation. 100 divided by the length of a list, multiplied by the for loops counter. This gives us a real number that can be put into the progress bar value. (code below)
Binder.daWindow.progUpdate = ((100.00 / databaseTables.Length) * dbTIndex);
I know this can be completed by threading (or whatever), but I would appreciate answers specifically for how this might be done by binding (unless it's impossible, then forget what I just said).
XAML:
<Window x:Name="DateWindow1" x:Class="WpfApp1.DateWindow"
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:WpfApp1"
xmlns:Main="using:DateWindow"
mc:Ignorable="d"
Title="Change Dates" Height="232.667" Width="462" Background="#FF2B2B2B" ResizeMode="NoResize">
<Grid>
<TextBox x:Name="DayChangeTextBox" HorizontalAlignment="Left" Height="30" Margin="176,45,0,0" TextWrapping="Wrap" Text="##" VerticalAlignment="Top" Width="58" FontSize="14" TextAlignment="Center" AcceptsReturn="False" AcceptsTab="False" GotFocus="DayChangeTextBox_GotFocus" LostFocus="DayChangeTextBox_LostFocus" BorderThickness="1" BorderBrush="Black" OpacityMask="Black" Background="#FFFDFDFD"/>
<Label Content="Days" HorizontalAlignment="Left" Margin="239,45,0,0" VerticalAlignment="Top" Width="42" FontSize="14" FontFamily="Microsoft YaHei UI" Height="30" Foreground="White"/>
<Label Content="Move Dates Forward:" HorizontalAlignment="Left" Margin="23,45,0,0" VerticalAlignment="Top" Width="144" FontSize="14" FontFamily="Microsoft JhengHei UI Light" Height="30" Foreground="White"/>
<Button x:Name="ChangeDatesButton" Content="Change Dates" HorizontalAlignment="Left" Margin="303,45,0,0" VerticalAlignment="Top" Width="143" Height="30" BorderThickness="1,1,2,3" BorderBrush="#FF474747" Click="ChangeDatesButton_Click" FontFamily="Microsoft YaHei UI" Background="#FFE6E6E6"/>
<Label x:Name="serverLabel" Content="Label" HorizontalAlignment="Left" Margin="10,73,0,0" VerticalAlignment="Top" RenderTransformOrigin="0.5,0.5" Width="5" Height="15" Visibility="Hidden"/>
<Label x:Name="databaseLabel" Content="Label" HorizontalAlignment="Left" Margin="20,73,0,0" VerticalAlignment="Top" Width="3" Visibility="Hidden" Height="15"/>
<Button x:Name="RevertToDefaultButton" Content="Revert to Backup" Margin="23,164,0,0" VerticalAlignment="Top" Height="30" Background="#FFE6E6E6" BorderBrush="#FF474747" BorderThickness="1,1,2,3" Click="RevertToDefaultButton_Click" FontFamily="Microsoft JhengHei UI" HorizontalAlignment="Left" Width="143"/>
<Button x:Name="OverwriteDefaultButton" Content="Backup Database" Margin="23,128,0,0" VerticalAlignment="Top" Height="30" BorderBrush="#FF474747" BorderThickness="1,1,2,3" Click="OverwriteDefaultButton_Click" FontFamily="Microsoft JhengHei UI" HorizontalAlignment="Left" Width="143" Background="#FFE6E6E6" />
<Button x:Name="CloseButton" Content="Close" Margin="0,164,10,0" VerticalAlignment="Top" Height="30" BorderBrush="#FF474747" BorderThickness="1,1,2,3" FontFamily="Microsoft JhengHei UI" Width="60" Click="CloseButton_Click" HorizontalAlignment="Right" Background="#FFE6E6E6" />
<Label x:Name="RevertBackupLabel" Content="Backup or Revert Database:" HorizontalAlignment="Left" Margin="12,93,0,0" VerticalAlignment="Top" Foreground="White" FontFamily="Microsoft JhengHei UI" FontWeight="Bold" FontSize="16"/>
<Label x:Name="DatesLabel" Content="Change Dates in Database:" Margin="12,10,0,0" Foreground="White" FontFamily="Microsoft JhengHei UI" FontWeight="Bold" FontSize="16" HorizontalAlignment="Left" Width="216" Height="30" VerticalAlignment="Top"/>
<ProgressBar HorizontalAlignment="Left" Height="13" Margin="303,80,0,0" VerticalAlignment="Top" Width="143" Name="pbStatus" Value="{Binding local.progUpdate, UpdateSourceTrigger=PropertyChanged}" Maximum="{Binding mx}" Minimum="{Binding mn}" LargeChange="0.01"/>
</Grid>
XAML CS Portion:
public static class Binder
{
public static DateWindow daWindow;
}
public partial class DateWindow : Window, INotifyPropertyChanged
{
private double _progUpdate;
public double progUpdate
{
get { return _progUpdate; }
set
{
_progUpdate = value;
if (PropertyChanged != null)
{
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(nameof(progUpdate)));
}
}
}
public double mx = 100;
public double mn = 0;
public event PropertyChangedEventHandler PropertyChanged;
public DateWindow()
{
InitializeComponent();
Binder.daWindow = this;
ChangeDateInDatabase ChangeDate = new ChangeDateInDatabase();
progUpdate = 25; // This is there so we can test the variable without going through the whole program.
}
private void ChangeDatesButton_Click(object sender, RoutedEventArgs e)
{
ChangeDateInDatabase ChangeDate = new ChangeDateInDatabase();
var result = MessageBox.Show("Are you sure you would like to change dates for " + Globals.selectedDatabase + " from server " + Globals.main.ServerComboBox.Text + "?", "Change Dates?", MessageBoxButton.YesNo, MessageBoxImage.Exclamation);
if (Globals.main.ServerComboBox.Text != "" && Globals.selectedDatabase != "" && FindDatabaseAndServer.Connector(Globals.main.ServerComboBox.Text, Globals.selectedDatabase) && result == MessageBoxResult.Yes)
{
try
{
long.Parse(DayChangeTextBox.Text);
ChangeDate.ChangeDates(this);
//ChangeDateInDatabase.ChangeDates(this);
}
catch
{
MessageBox.Show($"Invalid number {DayChangeTextBox.Text}, please enter a valid number.", "ERROR", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
}
(CLICK function serves the purpose of calling a method for the program. Inside the method, its main loop, which determines the methods completion, contains the variable desired to be bound with a defining equation for its value)
Method Containing Said Loop:
for (int dbTIndex = 0; dbTIndex < databaseTables.Length; dbTIndex++)
{
string[] dateColumns = new string[0];
string columnSelectQuery = "SELECT DATA_TYPE, COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '" + databaseTables[dbTIndex].ToString() + "' AND COLUMN_NAME LIKE '_%'";
using (SqlConnection connection2 = new SqlConnection(connectionString))
{
SqlCommand command2 = new SqlCommand(columnSelectQuery, connection2);
connection2.Open();
SqlDataReader reader2 = command2.ExecuteReader();
int y = 0;
while (reader2.Read())
{
if (reader2[0].ToString() == "datetime")
{
Array.Resize(ref dateColumns, dateColumns.Length + 1);
dateColumns[y] = reader2[1].ToString();
y++;
}
}
}
for (var dtColIndex = 0; dtColIndex < dateColumns.Length; dtColIndex++)
{
string addDatesQuery = "UPDATE " + databaseTables[dbTIndex] + " SET " + dateColumns[dtColIndex] + " = DATEADD(dd," + Convert.ToInt32(date.DayChangeTextBox.Text) + "," + dateColumns[dtColIndex] + ") WHERE " + dateColumns[dtColIndex] + " IS NOT NULL";
using (SqlConnection connection3 = new SqlConnection(connectionString))
{
SqlCommand command3 = new SqlCommand(addDatesQuery, connection3);
connection3.Open();
command3.ExecuteNonQuery();
}
}
//vvvvv VARIABLE THAT NEEDS TO BE BOUND vvvvvvv
Binder.daWindow.progUpdate = ((100.00 / databaseTables.Length) * dbTIndex);
}
(There is obviously more code to this part, which I can provide if needed)
Thanks in advance!
EDIT:
For the XAML, local.progUpdate is not the only thing I have tried. I've done path, progUpdate by itself, etc.
Your ProgressBar's first binding makes no sense: {Binding local.progUpdate, UpdateSourceTrigger=PropertyChanged}. You're not specifying a source, and there's no DataContext assigned anywhere, so the binding won't evaluate to anything because the path is meaningless. Because the property is on the window itself, you can just assign the window's data context to itself.
// DateWindow.xaml.cs
public DateWindow()
{
InitializeComponent();
DataContext = this;
...
}
<!-- DateWindow.xaml -->
<ProgressBar Value="{Binding progUpdate, Mode=OneWay}" ... />
Your other bindings will require mx and mn to be properties rather than fields.
Related
I am trying to get from my database one item, and when clicking on the next or previous button, I would like to get the next item out of my database by increasing its ID. I'm at the point of having my first item in my card, but when I click on previous or next, nothing happens.
I have in xaml:
<smtx:XamlDisplay Key="cards_1" Margin="4 4 0 0">
<materialDesign:Flipper Style="{StaticResource MaterialDesignCardFlipper}">
<materialDesign:Flipper.FrontContent>
<Grid Height="350" Width="200">
<Grid.RowDefinitions>
<RowDefinition Height="250" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<materialDesign:ColorZone Mode="PrimaryMid" VerticalAlignment="Stretch">
<materialDesign:PackIcon Kind="AccountCircle" Height="128" Width="128"
VerticalAlignment="Center" HorizontalAlignment="Center" />
</materialDesign:ColorZone>
<StackPanel Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock Text="{Binding CurrentGebruiker.Naam}"></TextBlock>
<Button Style="{StaticResource MaterialDesignFlatButton}" Foreground="DarkGoldenrod"
Command="{x:Static materialDesign:Flipper.FlipCommand}"
Margin="0 4 0 0"
>SHOW DETAILS</Button>
</StackPanel>
</Grid>
</materialDesign:Flipper.FrontContent>
And my viewmodel:
public ZoekMatchViewModel()
{
LeesGebruiker(1);
KoppelenCommands();
}
private Gebruiker currentGebruiker;
public Gebruiker CurrentGebruiker
{
get
{
return currentGebruiker;
}
set
{
currentGebruiker = value;
NotifyPropertyChanged();
}
}
private void KoppelenCommands()
{
NextCommand = new BaseCommand(VolgendeGebruiker);
PrevCommand = new BaseCommand(VorigeGebruiker);
}
public ICommand NextCommand { get; set; }
public ICommand PrevCommand { get; set; }
private void LeesGebruiker(int id)
{
//instantiƫren dataservice
ZoekMatchDataService zoekMatchDS =
new ZoekMatchDataService();
currentGebruiker = zoekMatchDS.GetGebruiker(id);
}
public void VolgendeGebruiker()
{
if (CurrentGebruiker != null)
{
int id = (currentGebruiker.ID) + 1;
LeesGebruiker(id);
}
}
public void VorigeGebruiker()
{
if (CurrentGebruiker != null)
{
int id = (currentGebruiker.ID) - 1;
LeesGebruiker(id);
}
}
My buttons:
<Button Command="{Binding PrevCommand}" Background="Transparent" BorderThickness="0" Height="50">
and
<Button Command="{Binding NextCommand}" Background="Transparent" BorderThickness="0" Height="50">
So the problem is that my xaml doesn't update to the new user when I click on next or previous buttons.
If you need more information, I'm happy to provide!
I think the "right" way to do this would be with a custom Selector. Selector is the base class used in WPF for a control that lets the user select one or more items from a list. For example: ComboBox and ListBox are both Selectors. If you've never made a custom control before this may be a bit complicated though.
There are a few simpler answers. You could make a class that holds all the data you want to display for a single option, and have your Window define a property of that type. Then you could bind all the variable parts of your interface to that property and just change the property value manually when the user clicks the left or right button. Of course you'd only be able to use this on one place, whereas if you made a custom control you could reuse it anywhere, any number of times.
I have a listbox, code below, that I'm populating with 900 items. When I scroll down the list quickly I get an exception of 'An ItemsControl is inconsistent with its items source'. Any ideas as to what is causing the issue?
<ListBox x:Name="FileList" ItemsSource="{Binding Files}" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.CanContentScroll="True"
MaxHeight="520" >
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<CheckBox x:Name="FileChecked" IsChecked="{Binding Checked}" Grid.Column="0" BorderThickness="1"/>
<Label Content="{Binding Name}" Grid.Column="1" />
<Label Content="{Binding Source}" Grid.Column="2" Style="{StaticResource FileProperties}" />
<Label Content="{Binding Destination}" Grid.Column="3" Style="{StaticResource FileProperties}"/>
<Label Content="{Binding ArchiveLocation}" Grid.Column="4" Style="{StaticResource FileProperties}"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
enter image description here
Here is a video of the issue. https://www.screencast.com/t/YUlp24zoXiG
I believe I've found the problem. I've pasted the problematic code below, so that other visitors can benefit from this answer.
// Your code from GitHub unchanged
private async void Preview_Click(object sender, System.Windows.RoutedEventArgs e)
{
vm.Files = new List<InstrumentFile>();
try
{
for (int i = 0; i < InstrumentList.Items.Count; i++)
{
ListBoxItem lbi = (InstrumentList.ItemContainerGenerator.ContainerFromIndex(i)) as ListBoxItem;
ContentPresenter cp = GetFrameworkElementByName<ContentPresenter>(lbi);
DataTemplate dt = InstrumentList.ItemTemplate;
CheckBox cb = (dt.FindName("InstrumentChecked", cp)) as CheckBox;
if (cb.IsChecked == true)
{
List<InstrumentFile> instrumentFiles = new List<InstrumentFile>();
Instrument instrument = ((Instrument)(InstrumentList.Items[i]));
string[] files = Directory.GetFiles(instrument.FileSource);
foreach (string file in files)
{
FileInfo fi = new FileInfo(file);
instrumentFiles.Add(new InstrumentFile()
{
Name = fi.Name,
Source = instrument.FileSource,
Destination = instrument.Destination,
ArchiveLocation = instrument.ArchiveLocation
});
}
if (string.IsNullOrEmpty(instrument.FileExt) == false)
{
IEnumerable<InstrumentFile> filteredFiles = instrumentFiles.Where(f => f.Name.ToUpper().EndsWith(instrument.FileExt.ToUpper()));
if (filteredFiles.Count() > 0)
vm.Files.AddRange(filteredFiles);
}
else
{
if (instrumentFiles.Count > 0)
vm.Files.AddRange(instrumentFiles);
}
}
}
}
catch (Exception ex)
{
await metroWindow.ShowMessageAsync("Exception Encountered", ex.Message, MessageDialogStyle.Affirmative, Helpers.DialogSettings());
}
FileCount.Content = vm.Files.Count.ToString() + " files";
}
Here, you're initializing the Files property in the view model. This causes the data-binding to be updated to an empty list. There's no problem so far. However, you then add things to Files, but these changes are not propagated to the data-binding system because the list in the view model is not an ObservableCollection.
You can fix this problem in a couple of ways. One type of fix is to set the Files property in the view model after you've created and filled the list. The new code would look like this (abbreviated):
private async void Preview_Click(object sender, System.Windows.RoutedEventArgs e)
{
// Create new variable to store the list
var files = new List<InstrumentFile>();
// You do a bunch of things, but you now add items to files, not to vm.Files
files.AddRange(filteredFiles);
// Finally, change Files
vm.Files = files
}
That last line will raise the PropertyChanged event in the view model to update the data-binding, but will do so with the full list of items.
The second kind of fix is to change the type of Files in your view model to ObservableCollection<InstrumentFile>. Any time you make a change to Files, the correct event will be raised to update the data-binding.
I have used tab control for view my usercontrols..
in 1st usercontrol
I have used datagrid to diplay Record and for Binding I have used generic List.
When want to change this List as per selected date then that collection is changed in database and in viewmodel also as List's set propery get executes but in view when i selected new tab and then go back to prevois tab at that time List's get property executes & then i am able get view as per selected date.
My main view and which contain 1st usercontrol as 1st tab item is given below:
Xaml code for above view is given below:
<DataGrid
Background="Transparent"
CanUserAddRows="True"
CanUserReorderColumns="False"
ItemsSource="{Binding Model_Transactions_TransactionsDetails_Jama,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
HeadersVisibility="Column">
</DataGrid>
<Grid DockPanel.Dock="Bottom" VerticalAlignment="Bottom" >
<Border BorderBrush="Black" BorderThickness="1" >
<Label HorizontalAlignment="Left" HorizontalContentAlignment="Right" Width="75" Content="{Binding SumOfWeightJama,UpdateSourceTrigger=PropertyChanged}" FontFamily="Segoe UI" FontWeight="Bold" FontSize="16" />
</Border>
</Grid>
<DataGrid
Background="Transparent"
CanUserAddRows="True"
CanUserReorderColumns="False"
ItemsSource="{Binding Model_Transactions_TransactionsDetails_Udhar,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
HeadersVisibility="Column">
</DataGrid>
<Grid DockPanel.Dock="Bottom" VerticalAlignment="Bottom">
<Border BorderBrush="Black" BorderThickness="1">
<Label Width="75" HorizontalAlignment="Left" HorizontalContentAlignment="Right" Content="{Binding SumOfWeightUdhar,UpdateSourceTrigger=PropertyChanged}" FontFamily="Segoe UI" FontWeight="Bold" FontSize="16"/>
</Border>
</Grid>
And View Model for above View is given below:
private DateTime _FilterDate ;
public DateTime FilterDate
{
get
{
return _FilterDate;
}
set
{
_FilterDate = value;
OnPropertyChanged("FilterDate");
Model_Transactions_TransactionsDetails_Jama = (ViewModel.AllDataCollactions.AllTransactionsDetails.Where(s => s.TransactionDate.Equals(FilterDate) && s.IsJama).OrderBy(s => s.TransactionsID)).ToList();
Model_Transactions_TransactionsDetails_Udhar = (ViewModel.AllDataCollactions.AllTransactionsDetails.Where(s => s.TransactionDate.Equals(FilterDate) && !s.IsJama).OrderBy(s => s.TransactionsID)).ToList();
}
}
public List<Model_TransactionsDetails> Model_Transactions_TransactionsDetails_Jama
{
get
{
return model_Transactions_TransactionsDetails_Jama;
}
set
{
model_Transactions_TransactionsDetails_Jama = value;
OnPropertyChanged("Model_Transactions_TransactionsDetails_Jama");
}
}
public List<Model_TransactionsDetails> Model_Transactions_TransactionsDetails_Udhar
{
get
{
return model_Transactions_TransactionsDetails_Udhar;
}
set
{
model_Transactions_TransactionsDetails_Udhar = value;
OnPropertyChanged("Model_Transactions_TransactionsDetails_Udhar");
}
}
public ViewModel_MasterBook()
{
FilterDate = DateTime.Now.AddDays(-1).Date;
InsertCommand = new RelayCommand(AddExecute, CanAdd);
}
Can any one help me How can i get view as per selected date immediately..
actually it should work i cant see an error. but when i use some kind of Lists in my WPF projects i use observablecollection with clear, add, delete.
but first i would change the binding
ItemsSource="{Binding Model_Transactions_TransactionsDetails_Jama,Mode=OneWay}"
because Mode=TwoWay makes no sense, you never set the itemssource from your datagrid to the viewmodel.
second i would change to ObservableCollection
public ObservableCollection<Model_TransactionsDetails> Model_Transactions_TransactionsDetails_Jama
{
get; private set;
}
with private setter because just initialize once.
//ctor
this.Model_Transactions_TransactionsDetails_Jama = new ObservableCollection<Model_TransactionsDetails>();
and then in your FilterDate setter fill the collection
this.Model_Transactions_TransactionsDetails_Jama.Clear();
var newdata = (ViewModel.AllDataCollactions.AllTransactionsDetails.Where(s => s.TransactionDate.Equals(FilterDate) && s.IsJama).OrderBy(s => s.TransactionsID)).ToList();
this.Model_Transactions_TransactionsDetails_Jama.AddRange(newdata);//AddRange is simply an extension method i wrote, you can simply use foreach and .Add()
I Have two views in MVVM(WPF). First View contains two Text boxes: User Name, Password, second view is having two Buttons: Submit and Clear. Both Views now set on On Form. When I press 'Clear' button both textboxes are cleared and in Submit a message of UserName and Password is displayed. I am using only MVVM+WPF, not prism.
ModelView Of First View:
class LoginView:ViewModelBase
{
string _userName;
public string UserName
{
get {return _userName ; }
set {
if (_userName != value)
{
_userName = value;
}
base.OnPropertyChanged(UserName);
}
}
string _Pwd;
public string PWD
{
get { return _Pwd; }
set
{
_Pwd = value;
base.OnPropertyChanged(_Pwd);
}
}
}
and For Button
class ButtonHandler
{
private DelegateCommand _ClearData;
public ICommand ClearCommand
{
get
{
if (_ClearData == null)
{
_ClearData = new DelegateCommand(ClearText);
}
return _ClearData;
}
}
LoginView lg = new LoginView();
private void ClearText()
{
lg.UserName = "";
lg.PWD = "";
}
}
and View Code of First Control
<Label Content="Login" Grid.Row="0" Grid.Column="1" VerticalAlignment="Top" HorizontalAlignment="Left"
FontFamily="Georgia" FontSize="24" FontWeight="UltraBold" ></Label>
<Label Content="User Name" Grid.Row="1" Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Left"></Label>
<Label Content="Password" Grid.Row="2" Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Left"></Label>
<TextBox Name="username" Grid.Row="1" Grid.Column="1" Margin="100,0,0,0" VerticalAlignment="Center" HorizontalAlignment="Left" Text="{Binding Path=UserName,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" ></TextBox>
<TextBox Name="pwd" Grid.Row="2" Grid.Column="1" Margin="100,0,0,0" VerticalAlignment="Center" HorizontalAlignment="Left" Text="{Binding Path=PWD,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"></TextBox>
<Separator Grid.Row="0" Grid.Column="1" Height="5" Margin="0,40,0,0" Background="Green"></Separator>
and Button View
<Button x:Name="Submit" Content="Submit" Grid.Column="1"></Button>
<Button x:Name="Clear" Content="Clear" Grid.Column="2"
Command="{Binding Path=ClearCommand, Mode=OneWay,
UpdateSourceTrigger=PropertyChanged}" >
</Button>
Why it is not working?
You are not using the MVVM pattern correctly, with this pattern the ViewModel should not have a reference to the View. A command is part of your ViewModel, therefore your reference to LoginView violates the pattern.
So you have two input fields and a button? for this I would have a single ViewModel and a single View. The ViewModel would expose two string properties (username & password) and a command that binds to the clear button. When the command executes it would clear the username and password texts on the ViewModel. The View will then update accordingly.
The basic principle of MVVM is to have a class that the view can bind to that has all the application logic inside of it. One of the main reasons is to have a separation of concerns. So if you want a username you expose a property that the view binds to and then when you want to log in you create a function that uses those bound values to submit to you business logic layer of your application.
This would seem to be one way to utilize MVVM in your example:
public class LoginViewModel
{
public string UserName {get;set;}//Implement INotifyPropertyChanged
public string PWD {get;set;}
private DelegateCommand _ClearData;
public ICommand ClearCommand
{
get
{
if (_ClearData == null)
{
_ClearData = new DelegateCommand(ClearText);
}
return _ClearData;
}
}
private void ClearText()
{
UserName = "";
PWD = "";
}
}
and then in your xaml:
<TextBox Text={Binding UserName} />
<TextBox Text={Binding PWD} />
<Button Command={Binding ClearCommand}/>
I'm new in Silverlight and I'm just trying to get a handle on how to do some things. What I'd like to do is have a chart, that has 2 lines that might overlap one another. What is happening with my code is that one line is displayed and then the next line is displayed, one after another rather than overlapping.
Here is my xaml
<navigation:Page x:Class="SilverlightNav1.Home"
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:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
xmlns:charting="clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=System.Windows.Controls.DataVisualization.Toolkit"
mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="547"
Title="Home"
Style="{StaticResource PageStyle}" xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit">
<Grid x:Name="LayoutRoot" Height="544">
<sdk:Label Height="28" HorizontalAlignment="Left" Margin="12,12,0,0" Name="label1" VerticalAlignment="Top" Width="120" Content="First Name" />
<TextBox Height="23" Margin="91,8,0,0" Name="txtFirstName" VerticalAlignment="Top" HorizontalAlignment="Left" Width="120" >
<TextBox.RenderTransform>
<SkewTransform AngleX="2" AngleY="12" />
</TextBox.RenderTransform>
<TextBox.Effect>
<DropShadowEffect />
</TextBox.Effect>
</TextBox>
<Button Content="Greet Me" Height="23" HorizontalAlignment="Left" Margin="91,72,0,0" Name="GreetMe" VerticalAlignment="Top" Width="75" Click="GreetMe_Click" />
<TextBlock Margin="91,116,25,0" Name="Greeting" Text="" Height="105" VerticalAlignment="Top" FontSize="20" />
<toolkit:Chart HorizontalAlignment="Left" Margin="21,246,0,0" Name="chart1" Title="Testing graph" VerticalAlignment="Top" Height="249" Width="400">
<toolkit:Chart.Series>
<toolkit:LineSeries Title="Guys" ItemsSource="{Binding p}" IndependentValueBinding="{Binding FirstName}" DependentValueBinding="{Binding Greeting}" Name="testGraph">
</toolkit:LineSeries>
<toolkit:LineSeries Title="Girls" ItemsSource="{Binding girls}" IndependentValueBinding="{Binding FirstName}" DependentValueBinding="{Binding Greeting}" Name="lsGirls">
</toolkit:LineSeries>
</toolkit:Chart.Series>
</toolkit:Chart>
</Grid>
Here is my code-behind.
List<Model.Person> p = new List<Model.Person>();
p.Add(new Model.Person() { FirstName = "Bob", Greeting = 1 });
p.Add(new Model.Person() { FirstName = "Phil", Greeting = 3 });
p.Add(new Model.Person() { FirstName = "Dennis", Greeting = 4});
p.Add(new Model.Person() { FirstName = "Chewie", Greeting = 2 });
//this.DataContext = p;
List<Model.Person> girls = new List<Model.Person>();
girls.Add(new Model.Person() { FirstName = "Jamie", Greeting = 4 });
girls.Add(new Model.Person() { FirstName = "Abby", Greeting = 7 });
girls.Add(new Model.Person() { FirstName = "M", Greeting = 5 });
girls.Add(new Model.Person() { FirstName = "K", Greeting = 6 });
((LineSeries)chart1.Series[0]).ItemsSource = p;
((LineSeries)chart1.Series[1]).ItemsSource = girls;
And finally here is my class defined in person.cs
namespace SilverlightNav1.Model
{
public class Person
{
private string _firstName;
public string FirstName
{
get { return _firstName; }
set
{
_firstName = value;
}
}
private int _greeting;
public int Greeting
{
get { return _greeting; }
set { _greeting = value; }
}
}
}
An issue is that both data sets have different X-axis values - Bob and Jamie are not the same, for example, so the toolkit will not show them on the same X-axis value. You can see how this could be fixed by changing the girls data set FirstName's to Bob, Phil, Dennis, and Chewie.
One option is to assign a increasing numeric counter to both guys and girls sets, and use that as the X-axis, so that they can be graphed together. So have the X-axis be bound to the "Counter" property, and have bob/phil/dennis/chewie have respective values of 0,1,2, and 3, and the same for Jamie through K. You could style the graph to display the actual FirstName next to the datapoint itself, or another such method.