Reputation: 91
I am working on Data Management project which was designed in WinForms and not I am redesigning it in WPF(MVVM) I am using caliburn micro obviously to reduce development time and flexibility, I came across a huddle where I want to refresh the Data Grid as soon as I save the data into Database. Here is explanation of what i want to achieve.
1) GameModel : Contains 5 properties same as Database(GameID,GameName,GameCategory,GameCompany,GamePrice)
private string _gameID;
private string _gameName;
private string _gameComp;
private string _gameCat;
private int _gamePrice;
public int GamePrice
{
get { return _gamePrice; }
set
{
_gamePrice = value;
NotifyOfPropertyChange(() => GamePrice);
}
}
public string GameCat
{
get { return _gameCat; }
set { _gameCat = value;
NotifyOfPropertyChange(() => GameCat);
}
}
public string GameComp
{
get { return _gameComp; }
set { _gameComp = value;
NotifyOfPropertyChange(() => GameComp);
}
}
public string GameName
{
get { return _gameName; }
set { _gameName = value;
NotifyOfPropertyChange(() => GameName);
}
}
public string GameID
{
get { return _gameID; }
set { _gameID = value;
NotifyOfPropertyChange(() => GameID);
}
}
2) GameData (DataAccessLayer): Contains method to Add data into database for sake of simplicity I am using DataTable for this example to get the answer.
DataTable dt;
public GameData()
{
dt = new DataTable("gameMaster");
DataColumn col1 = new DataColumn("Srno", typeof(int));
col1.AutoIncrement = true;
col1.AutoIncrementSeed = 1;
dt.Columns.Add(col1);
dt.Columns.Add("GameID", typeof(string));
dt.Columns.Add("GameName", typeof(string));
dt.Columns.Add("GameComp", typeof(string));
dt.Columns.Add("GameCat", typeof(string));
dt.Columns.Add("GamePrice", typeof(int));
}
public bool AddNewGame(GameModel gm)
{
try
{
dt.Rows.Add(null, gm.GameID, gm.GameName, gm.GameComp, gm.GameCat, gm.GamePrice);
return true;
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
return false;
}
}
public List<GameModel> GetAllGames()
{
var gameList = new List<GameModel>();
foreach(DataRow row in dt.Rows)
{
var game = new GameModel
{
GameID = row[1].ToString(),
GameName = row[2].ToString(),
GameComp= row[3].ToString(),
GameCat= row[4].ToString(),
GamePrice= (int)row[5],
};
gameList.Add(game);
}
return gameList;
}
3) GameViewModel : Contains ObservableCollection which gets data from GameData : GetAllGames method.
public GameData _gameData;
public GameModel _gameModel;
public GameViewModel()
{
GameCat.Add("Action");
GameCat.Add("Arcade");
GameCat.Add("Racing");
GameCat.Add("Puzzle");
GameCat.Add("Other");
GameComp.Add("EA");
GameComp.Add("EA Sports");
GameComp.Add("Ubisoft");
_gameData = new GameData();
RefreshGames();
}
private ObservableCollection<GameModel> _allGames;
public ObservableCollection<GameModel> AllGames
{
get { return _allGames; }
set
{
_allGames = value;
NotifyOfPropertyChange(() => AllGames);
}
}
public void AddNewGame(string gameID, string gameName, string gameCat, string gameComp, int gamePrice)
{
_gameModel = new GameModel
{
GameID = gameID,
GameName = gameName,
GameCat = gameCat,
GameComp = gameComp,
GamePrice = gamePrice
};
if (_gameData.AddNewGame(_gameModel))
{
RefreshGames();
MessageBox.Show("Game Added succesfully !");
}
}
public void RefreshGames()
{
var obj = new ObservableCollection<GameModel>(_gameData.GetAllGames());
AllGames = obj;
}
Here I've to use another method in order to Refresh the ObservableCollection or you can say to populate data from DB. I want that whenever I add any data this should be automatically done. How to make it aware that any insertion was done.
And for reference I am sharing the last portion of the code View as follow :
<!--row1-->
<TextBox Grid.Row="1" Grid.Column="1" materialDesign:HintAssist.Hint="GameID" materialDesign:HintAssist.IsFloating="True" x:Name="GameID"/>
<!--row2-->
<TextBox Grid.Row="2" Grid.Column="1" x:Name="GameName"/>
<!--row3-->
<ComboBox Grid.Row="3" Grid.Column="1" x:Name="GameCat" SelectedIndex="0"/>
<!--row4-->
<ComboBox Grid.Row="4" Grid.Column="1" x:Name="GameComp" SelectedIndex="0"/>
<!--row5-->
<TextBox Grid.Row="5" Grid.Column="1" x:Name="GamePrice"/>
<!--row6-->
<StackPanel Orientation="Horizontal" Grid.Row="6" Grid.Column="1" HorizontalAlignment="Right">
<Button Content="Save" Width="60" x:Name="AddNewGame"/>
<Button Content="Exit" Width="60" x:Name="Exit"/>
</StackPanel>
<!--row7-->
<ListView Grid.Column="1" Grid.Row="7" ItemsSource="{Binding Path=AllGames}">
<ListView.View>
<GridView>
<GridViewColumn Header="GameID" Width="Auto" DisplayMemberBinding="{Binding Path=GameID}"/>
<GridViewColumn Header="GameName" Width="Auto" DisplayMemberBinding="{Binding Path=GameName}"/>
<GridViewColumn Header="Category" Width="Auto" DisplayMemberBinding="{Binding Path=GameComp}"/>
<GridViewColumn Header="Company" Width="Auto" DisplayMemberBinding="{Binding Path=GameCat}"/>
<GridViewColumn Header="Price" Width="Auto" DisplayMemberBinding="{Binding Path=GamePrice}"/>
</GridView>
</ListView.View>
</ListView>
Binding Works Fine, Data is showing fine but I want it to be done Automatically, Please let me know how can i do this without calling the RefreshGames method.
Thank you in Advance and sorry if this question is long but for sake of understanding i had to put everything.
if any one wants to share their review on Code please share it.
Upvotes: 0
Views: 2301
Reputation: 12276
An observablecollection notifies collection changed when you add or remove entries from it. You seem to be talking about
public ObservableCollection<GameModel> AllGames
Which is in the same viewmodel as AddNewGame. If you just do
AllGames.Add(_gameModel);
In AddNewGame.
Then your ListView will show the new game as a new row.
An assumption here is that the one user is adding and viewing the games.
In a situation where other users could insert a new game and you want to see that appear then the simple solution is to poll the database every few minutes.
That isn't practical if you have a LOT of users and a lot of data changing but this doesn't look like that sort of a requirement.
Upvotes: 0