TB007
Member
- Joined
- Aug 13, 2022
- Messages
- 24
- Programming Experience
- Beginner
I have a fairly simple WPF app which primarily has 2 datagrid's in two different tabitem's.
The datagrid in 1st tabitem has the itemssource
The datagrid in 2nd tabitem has the itemssource
Now when I select a row from the datagrid in 2nd tabitem its different column data are shown in a GroupBox which has an ItemsControl with an ItemTemplate as shown below to basically do CRUD operations
My main ViewModel looks something like this
Currently there are a couple of issues that I'm having
1) a) When I add a new entry in the database by first hitting the Add button then fill up the data in the TextBox's and hit the Save button, if the Party is already present in the database it automatically updates the datagrid in the 2nd tabitem but doesn't in the 1st tabitem.
b) If the Party is completely new then none of the datagrid's show the new data and neither the combo box add's this new Party to its items. It only reflects when I restarst the app as the data is updated in the actual database.
2) When I delete an entry by hitting the Delete button though both the datagrid's view are updated but if the deleted entries Party no longer exists now after the deletion then it should also disappear from the combo box items but that is not happening. Once again I need to restart to app get the effect.
How do I solve these issues ? I've been struggling with this for quite a long time now so can anyone help me fix this ?
My full project can be found here for testing/better understanding.
The datagrid in 1st tabitem has the itemssource
PendingBills
which is an ICollectionView and it shows some filtered data as per some basic logicThe datagrid in 2nd tabitem has the itemssource
AllBills
which is also an ICollectionView and it shows some filtered data using the selected item of combo box SelectedCBItem
.
C#:
<DataGrid ItemsSource="{Binding AllBills}" SelectedItem="{Binding SelectedInv}" SelectionMode="Single" SelectedIndex="{Binding SelectedIndex}" ...>
Now when I select a row from the datagrid in 2nd tabitem its different column data are shown in a GroupBox which has an ItemsControl with an ItemTemplate as shown below to basically do CRUD operations
C#:
<DataTemplate x:Key="UserGrid">
<Border Background="Transparent" BorderBrush="White" BorderThickness="1" CornerRadius="5" >
<Grid Margin="10">
...
<TextBox Text="{Binding Party, BindingGroupName=Group1, UpdateSourceTrigger=Explicit}" Grid.Column="1" Grid.Row="1"/>
<TextBox Text="{Binding BillNo, BindingGroupName=Group1, UpdateSourceTrigger=Explicit}" Grid.Column="1" Grid.Row="2"/>
<TextBox Text="{Binding BillDt, BindingGroupName=Group1, UpdateSourceTrigger=Explicit}" Grid.Column="1" Grid.Row="3"/>
<TextBox Text="{Binding Amt, BindingGroupName=Group1, UpdateSourceTrigger=Explicit}" Grid.Column="1" Grid.Row="4"/>
<TextBox Text="{Binding DueDt, BindingGroupName=Group1, UpdateSourceTrigger=Explicit}" Grid.Column="1" Grid.Row="5"/>
<TextBox Text="{Binding PaidOn, BindingGroupName=Group1, UpdateSourceTrigger=Explicit}" Grid.Column="1" Grid.Row="6"/>
<StackPanel Orientation="Horizontal" Grid.Row="10" Grid.ColumnSpan="2" HorizontalAlignment="Right" Margin="5,5,5,5">
<Button Content="Cancel" Command="{Binding DataContext.CancelCommand, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" Margin="4,0"/>
<Button Content="Delete" Command="{Binding DataContext.DeleteUserCommand, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" Margin="4,0"/>
<Button Content="Save" Command="{Binding DataContext.SaveCommand, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" Margin="4,0"/>
<Button Content="Add" Command="{Binding DataContext.AddCommand, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" Margin="4,0"/>
</StackPanel>
</Grid>
</Border>
</DataTemplate>
...
<GroupBox Grid.Row="4" Header="CRUD Form" BorderThickness="0" Foreground="LightPink">
<ItemsControl BindingGroup="{Binding UpdateBindingGroup, Mode=OneWay}" VerticalAlignment="Top" Margin="5,5,5,5" Grid.Column="1"
ItemTemplate="{StaticResource UserGrid}" ItemsSource="{Binding SelectedInv, Converter={StaticResource SelectedItemToItemsSource}}" />
<GroupBox.Style>
<Style TargetType="GroupBox">
<Style.Triggers>
<DataTrigger Binding="{Binding SelectedInv}" Value="{x:Null}">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</GroupBox.Style>
</GroupBox>
My main ViewModel looks something like this
C#:
public class BillsViewModel : ViewModelBase
{
...
public ICollectionView PendingBills { get; private set; }
private ObservableCollection<Bills> _allBills;
...
public BillsViewModel()
{
...
_allBills = DatabaseLayer.GetAllBillsFromDB();
ComboItems = new ObservableCollection<string>(_allBills.Select(b => b.Party).Distinct().OrderBy(b => b).ToList());
PendingBills = new ListCollectionView(_allBills)
{
Filter = o => ((Bills)o).PaidOn=="" && (DateTime.ParseExact(((Bills)o).DueDt, "yyyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture) >= DateTime.Today.AddDays(-50) && DateTime.ParseExact(((Bills)o).DueDt, "yyyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture) < DateTime.Today.AddDays(50))
};
AllBills = new ListCollectionView(_allBills)
{
Filter = o => ((Bills)o).Party == SelectedCBItem
};
bills = new BillsBusinessObject();
bills.BillChanged += new EventHandler(bills_BillChanged);
UpdateBindingGroup = new BindingGroup { Name = "Group1" };
CancelCommand = new RelayCommand(DoCancel);
SaveCommand = new RelayCommand(DoSave);
AddCommand = new RelayCommand(AddUser);
DeleteUserCommand = new RelayCommand(DeleteUser);
}
...
private ICollectionView _allBillsCollection;
public ICollectionView AllBills
{
get { return _allBillsCollection; }
set
{
_allBillsCollection = value;
SetValue(ref _allBillsCollection, value);
}
}
public ObservableCollection<string> ComboItems { get; private set; }
...
BillsBusinessObject bills;
private ObservableCollection<Bills> _Bill;
public ObservableCollection<Bills> Bill
{
get
{
_Bill = new ObservableCollection<Bills>(bills.GetBills());
return _Bill;
}
}
public int SelectedIndex { get; set; }
object _SelectedInv;
public object SelectedInv
{
get
{
return _SelectedInv;
}
set
{
if (_SelectedInv != value)
{
_SelectedInv = value;
OnPropertyChanged("SelectedInv");
}
}
}
private BindingGroup _UpdateBindingGroup;
public BindingGroup UpdateBindingGroup
{
get
{
return _UpdateBindingGroup;
}
set
{
if (_UpdateBindingGroup != value)
{
_UpdateBindingGroup = value;
OnPropertyChanged("UpdateBindingGroup");
}
}
}
void bills_BillChanged(object sender, EventArgs e)
{
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
{
OnPropertyChanged("Bill");
}));
}
public RelayCommand CancelCommand { get; set; }
public RelayCommand SaveCommand { get; set; }
public RelayCommand AddCommand { get; set; }
public RelayCommand DeleteUserCommand { get; set; }
void DoCancel(object param)
{
UpdateBindingGroup.CancelEdit();
if (SelectedIndex == -1) //This only closes if new
SelectedInv = null;
}
void DoSave(object param)
{
UpdateBindingGroup.CommitEdit();
var bill = SelectedInv as Bills;
if (SelectedIndex == -1)
{
bills.AddBill(bill);
_allBills.Add(bill);
OnPropertyChanged("Bill"); // Update the observablecollection from the data source
MessageBox.Show("Data Saved Successfully.");
}
else
{
bills.UpdateBill(bill);
MessageBox.Show("Data Updated Successfully.");
}
SelectedInv = null;
PendingBills.Refresh();
OnPropertyChanged("Cnt");
}
void AddUser(object param)
{
SelectedInv = null; // Unselects last selection. Essential, as assignment below won't clear other control's SelectedItems
var bill = new Bills();
SelectedInv = bill;
}
void DeleteUser(object parameter)
{
var bill = SelectedInv as Bills;
if (SelectedIndex != -1)
{
bills.DeleteBill(bill);
OnPropertyChanged("Bill"); // Update the observablecollection from the data source
if (!_allBills.Select(a=>a.Party).Distinct().ToList().Contains(bill.Party)) //If the data source no longer has any such "Party" then remove it from combo box items
{
ComboItems.Remove(bill.Party.ToString());
}
}
else
{
SelectedInv = null; // Simply discard the new object
}
_allBills.Remove(bill);
AllBills.Refresh();
PendingBills.Refresh();
MessageBox.Show("Data Deleted Successfully.");
}
}
Currently there are a couple of issues that I'm having
1) a) When I add a new entry in the database by first hitting the Add button then fill up the data in the TextBox's and hit the Save button, if the Party is already present in the database it automatically updates the datagrid in the 2nd tabitem but doesn't in the 1st tabitem.
b) If the Party is completely new then none of the datagrid's show the new data and neither the combo box add's this new Party to its items. It only reflects when I restarst the app as the data is updated in the actual database.
2) When I delete an entry by hitting the Delete button though both the datagrid's view are updated but if the deleted entries Party no longer exists now after the deletion then it should also disappear from the combo box items but that is not happening. Once again I need to restart to app get the effect.
How do I solve these issues ? I've been struggling with this for quite a long time now so can anyone help me fix this ?
My full project can be found here for testing/better understanding.