티스토리 뷰
메뉴를 선택해서 주문 목록체 추가하는 부분을 작업합니다.
1. SelectMenu.xaml
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Margin="10">
<b:Interaction.Triggers>
<b:EventTrigger EventName="MouseDown">
<b:InvokeCommandAction Command="{Binding RelativeSource={RelativeSource AncestorType=ItemsControl}, Path=DataContext.SelectProductCommand}" CommandParameter="{Binding}" />
</b:EventTrigger>
</b:Interaction.Triggers>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Image Source="{Binding ImageUri}" Stretch="UniformToFill" />
<StackPanel Grid.Row="1">
<TextBlock
HorizontalAlignment="Stretch"
Text="{Binding Name}"
TextAlignment="Center" />
<TextBlock
HorizontalAlignment="Stretch"
Text="{Binding Price, StringFormat={}{0:N0}}"
TextAlignment="Center" />
</StackPanel>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
상품을 선택하면 뷰모델에 커맨드를 실행해서 주문을 추가해야 합니다.
1-1. EventTrigger를 이용해서 MouseDown 이벤트가 발생하면 InvokeCommandAction을 이용해서 뷰모델에 커맨드를 실행합니다.
<b:Interaction.Triggers>
<b:EventTrigger EventName="MouseDown">
<b:InvokeCommandAction />
</b:EventTrigger>
</b:Interaction.Triggers>
1-2. 위의 코드는 DataTemplate에 내부에 있기 때문에, ViewModel을 찾기 위해서는 RelativeSource를 이용해야 합니다.
<b:InvokeCommandAction
Command="{Binding RelativeSource={RelativeSource AncestorType=ItemsControl},
Path=DataContext.SelectProductCommand}"
CommandParameter="{Binding}" />
* RelativeSource AncestorType=ItemsControl : 현재 VisualTree 위치에서부터 위로 올라가면서 처음 만나는 ItemsControl을 찾습니다.
* Path=DataContext.SelectProductCommand : ItemsControl을 찾으면 DataContext.SelectProductCommand를 실행합니다.
* ItemsControl의 DataContext에는 ViewModel이 들어가 있기 때문에 DataContext.SelectProductCommand라고 하면 내가 원하는 커맨드를 찾을 수 있기 때문입니다.
DataContext에 어떻게 ViewModel이 들어가는지 모르시는 경우 여기를 참고하시면 됩니다.
* CommandParameter="{Binding}" : 현재 위치가 DataTemplate이기 때문에 여기서 이야기하는 {Binding} 은 데이터를 가르키게 됩니다.
* 한글로 풀어서 이야기하면, 사용자가 마우스 다운 이벤트를 발생시키면, SelectProductCommand를 실행시키는데, 파라메터는 지금 표시하는 데이터를 가지고 가라~ 정도가 될 것 같습니다.
1-3. DataGrid
<DataGrid
AutoGenerateColumns="False"
IsReadOnly="True"
ItemsSource="{Binding AppContext.CurrentOrder.Items}">
<DataGrid.Columns>
<DataGridTextColumn
Width="200"
Binding="{Binding ProductName}"
Header="메뉴명" />
<DataGridTextColumn
Width="100"
Binding="{Binding UnitPrice, StringFormat={}{0:N0}}"
Header="단가"
TextBlock.TextAlignment="Right" />
<DataGridTextColumn
Width="60"
Binding="{Binding Quantity, StringFormat={}{0:N0}}"
Header="수량" />
<DataGridTextColumn
Width="100"
Binding="{Binding Amount, StringFormat={}{0:N0}}"
Header="금액" />
</DataGrid.Columns>
</DataGrid>
* ItemsSource="{Binding AppContext.CurrentOrder.Items}" : AppContext에 CurrentOrder가 현재 진행 중인 주문을 가리키고, 사용자가 메뉴를 추가하면 Items에 입력됩니다. 그 목록을 DataGrid에 출력합니다.
* 키오스크이다보니 Column에 Width를 고정값으로 입력했습니다.
* Binding="{Binding UnitPrice, StringFormat={}{0:N0}}" : 숫자형의 데이터를 출력할때 이렇게 사용하면 소숫점 없이 정수만 출력되며, 3자리마다 ,가 추가됩니다.
2. SelectMenuViewModel.cs
/// <summary>
/// 메뉴 선택 커맨드
/// </summary>
public ICommand SelectProductCommand { get; set; }
private void Init()
{
//...
SelectProductCommand = new DelegateCommand<Product>(OnSelectProduct);
PaymentCommand = new DelegateCommand(OnPayment);
}
private void OnSelectProduct(Product product)
{
AppContext.CurrentOrder.Items.Insert(0,
new OrderDetail
{
OrderId = AppContext.CurrentOrder.OrderId,
ProductName = product.Name,
UnitPrice = product.Price,
Quantity = 1,
Amount = product.Price * 1
});
AppContext.CurrentOrder.UpdateProperties();
}
* SelectProductCommand를 실행할 때 CommandParameter를 이용하려면, 커맨드를 생성할 때 입력받는 데이터유형을 지정해야 합니다.
* 일반적으로는 string, object등을 사용하지만, 여기서는 데이터의 유형을 정확하게 알기 때문에 Product라고 지정을 했습니다.
* AppContext.CurrentOrder.Items.Insert : 신규 아이템을 목록에 추가합니다. 이 때 추가된 데이터가 화면에 바로바로 보이기 위해서는 ObservableCollection으로 생성되어 있어야 합니다.
/// <summary>
/// 아이템들
/// </summary>
public IList<OrderDetail> Items { get; set; } = new ObservableCollection<OrderDetail>();
주의!!!!
처음 생성을 ObservableCollection을 했지만, 다른 코드에서 Items = aaaList.ToList() 등의 코드를 이용해서 List 형으로 변경해서 입력하면, 더 이상 데이터의 추가/삭제 내용이 화면에 바로 반영되지 않습니다.
Items.Clear(), Items.Add(), Items.Insert(), Items.Remove() 등의 메서드를 이용해서만 작업해야 합니다.
3. Order.cs
/// <summary>
/// 프로퍼티 업데이트
/// </summary>
public void UpdateProperties()
{
TotalQuantity = Items.Sum(x => x.Quantity);
TotalAmount = Items.Sum(x => x.Amount);
}
주문을 추가한 후에 총 수량과 총 금액을 업데이트 하는 메서드를 추가했습니다.
이 부분도 Items 프로퍼티를 INotifyCollectionChanged 형으로 변경한 후 추가/삭제시 자동으로 금액을 계산할 수 있지만, 이벤트 핸들러를 추가하고 사용해야 하기 때문에 권장하지는 않습니다.
4. 소스
kaki104/PrismKiosk at Part5/select-menu-addorder (github.com)
'WPF .NET' 카테고리의 다른 글
Kiosk 만들기 - Part7 (0) | 2023.10.30 |
---|---|
Kiosk 만들기 - Part6 (0) | 2023.10.27 |
Kiosk 만들기 - Part4 (2) | 2023.10.23 |
Kiosk 만들기 - Part3 (0) | 2023.10.20 |
Prism - ContentControl에 화면 생성해서 넣기 1/2 (2) | 2023.10.19 |
- Total
- Today
- Yesterday
- #MVVM
- LINQ
- Always Encrypted
- Behavior
- kiosk
- #uwp
- PRISM
- #Windows Template Studio
- Build 2016
- .net 5.0
- uno-platform
- XAML
- visual studio 2019
- UWP
- dotNETconf
- MVVM
- IOT
- C#
- Windows 10
- ef core
- uno platform
- #prism
- windows 11
- Visual Studio 2022
- Bot Framework
- .net
- Cross-platform
- Microsoft
- ComboBox
- WPF
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |