I'm working on a WIN 8.1 App. In my App I have a ListView where I'm binding a observable collection from a ViewModel. So far everything works fine. The Problem is, that in the Background all the Data will be loaded correctly, but my ListView displays after approximately 40 elements, from the beginning... In the Background the right Object is selected and 80 Objects are loaded.
Could it be a Problem with the Scrolling?
Does anyone know, how to solve this issue?
From an other Page, i navigate to the Page with the ListView:
private void ShowReturnData()
{
ReturnViewModel retVM = new ReturnViewModel(_navigationService, SelectedTour);
_navigationService.NavigateTo(ViewModelLocator.ReturnPageKey, retVM);
}
In my ViewModel Constructor, I add my data to the observable Collection:
I'm working with MVVMlight.
Properties (ObservableCollection, SelectedItem):
--> observable Collection
/// <summary>
/// The <see cref="Data" /> property's name.
/// </summary>
public const string DataPropertyName = "Data";
private ObservableCollection<ReturnData> _myProperty = new ObservableCollection<ReturnData>();
/// <summary>
/// Sets and gets the Data property.
/// Changes to that property's value raise the PropertyChanged event.
/// </summary>
public ObservableCollection<ReturnData> Data
{
get
{
return _myProperty;
}
set
{
if (_myProperty == value)
{
return;
}
_myProperty = value;
RaisePropertyChanged(DataPropertyName);
}
}
--> SelectedItem
/// <summary>
/// The <see cref="SelectedItem" /> property's name.
/// </summary>
public const string SelectedItemPropertyName = "SelectedItem";
private ReturnData _selectedItem = null;
/// <summary>
/// Sets and gets the SelectedTour property.
/// Changes to that property's value raise the PropertyChanged event.
/// </summary>
public ReturnData SelectedItem
{
get
{
return _selectedItem;
}
set
{
if (_selectedItem == value)
{
return;
}
if (_selectedItem != null)
{
_selectedItem.IsFirstItem = false;
_selectedItem.IsLastItem = false;
}
_selectedItem = value;
if (_selectedItem != null)
{
setIsFirstOrLastItem(Data.IndexOf(_selectedItem));
}
RaisePropertyChanged(SelectedItemPropertyName);
}
}
ViewModel Constructor:
public ReturnViewModel(INavigationService navigationService, TourDetailData tourDetails)
{
//Services
_navigationService = navigationService;
//Commands
PrevPageCommand = new RelayCommand(GoToPrevPage);
TourDetails = tourDetails;
TourCustomerName = "Tour " + tourDetails.Tour + " > " + tourDetails.AccountName;
Data = new ObservableCollection<ReturnData>(from i in TourDetails.ReturnData orderby Convert.ToInt32(i.ItemId) select i);
}
XAML:
<ListView x:Name="lvItems"
Grid.Row="2"
SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
ItemTemplate="{StaticResource ReturnDataTemplate}"
ItemContainerStyle="{StaticResource ReturnDataListViewItemStyle}"
ItemsSource="{Binding Data}"
Margin="0,5,0,0"
Loaded="lvItems_Loaded">
</ListView>
DataTemplate:
<DataTemplate x:Key="ReturnDataTemplate">
<Grid x:Name="grid" d:DesignWidth="1344.53" d:DesignHeight="123.228">
<Grid.Resources>
<converter:SelectionConverter x:Key="SelectionConverter" Context="{Binding}" />
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="450*"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
</Grid.ColumnDefinitions>
<Rectangle Grid.Row="0" Grid.ColumnSpan="5" Height="100" Fill="LightGray" Visibility="Collapsed"/>
<Rectangle Grid.Row="2" Grid.ColumnSpan="5" Height="100" Fill="LightGray" Visibility="Collapsed"/>
<!--<Rectangle Grid.Row="0" Grid.ColumnSpan="5" Height="100" Fill="LightGray" Visibility="{Binding IsFirstItem, Converter={StaticResource BoolToVisibilityConverter}}"/>
<Rectangle Grid.Row="2" Grid.ColumnSpan="5" Height="100" Fill="LightGray" Visibility="{Binding IsLastItem, Converter={StaticResource BoolToVisibilityConverter}}"/>-->
<Rectangle Grid.Row="1" Fill="{StaticResource OrangeHighlight}" Visibility="{Binding IsDirty, Converter={StaticResource BoolToVisibilityConverter}}"/>
<StackPanel Grid.Row="1" Grid.Column="1" VerticalAlignment="Center" Margin="15,0">
<TextBlock TextWrapping="Wrap" FontSize="42.667" FontFamily="Segoe UI" Text="{Binding ItemId}" FontWeight="SemiBold"/>
<TextBlock TextWrapping="Wrap" Text="{Binding ItemName}" FontSize="32" FontFamily="Segoe UI"/>
</StackPanel>
<!--<TextBox x:Name="tbxReturn" Grid.Row="1" TextWrapping="Wrap" Grid.Column="2" FontFamily="Segoe UI" FontSize="42.667" Text="{Binding Return}" HorizontalAlignment="Center" VerticalAlignment="Center" Style="{StaticResource TextBoxStyleValues}" PreventKeyboardDisplayOnProgrammaticFocus="True" DoubleTapped="tbxReturn_DoubleTapped" GotFocus="tbxReturn_GotFocus" />-->
<TextBox x:Name="tbxReturn" Grid.Row="1" TextWrapping="Wrap" Grid.Column="2" FontFamily="Segoe UI" FontSize="42.667" Text="{Binding Return}" HorizontalAlignment="Center" VerticalAlignment="Center" Style="{StaticResource TextBoxStyleValues}" DoubleTapped="tbxReturn_DoubleTapped" GotFocus="tbxReturn_GotFocus" InputScope="CurrencyAmountAndSymbol" Foreground="#FF520164" />
<TextBox x:Name="tbxMold" Grid.Row="1" TextWrapping="Wrap" Text="{Binding Mildew}" Grid.Column="3" FontFamily="Segoe UI" FontSize="42.667" HorizontalAlignment="Center" VerticalAlignment="Center" Style="{StaticResource TextBoxStyleValues}" DoubleTapped="tbxMold_DoubleTapped" Tapped="tbxMold_Tapped" GotFocus="tbxMold_GotFocus" InputScope="CurrencyAmountAndSymbol" Foreground="#FF019E90" />
<TextBox x:Name="tbxCredit" Grid.Row="1" TextWrapping="Wrap" Text="{Binding Credit}" Grid.Column="4" FontFamily="Segoe UI" FontSize="42.667" HorizontalAlignment="Center" VerticalAlignment="Center" Style="{StaticResource TextBoxStyleValues}" DoubleTapped="tbxCredit_DoubleTapped" Tapped="tbxCredit_Tapped" GotFocus="tbxCredit_GotFocus" InputScope="CurrencyAmountAndSymbol" Foreground="#FF005C9C" />
<!--<Button Grid.Row="1" Content="+" HorizontalAlignment="Stretch" VerticalAlignment="Top" Grid.Column="2" Height="100" Margin="0,-100,0,0" FontSize="48" Style="{StaticResource NumUpDownButtonStyle}" Visibility="{Binding ElementName=lvItems, Path=DataContext.SelectedItem, ConverterParameter=Selected, Converter={StaticResource SelectionConverter}}" Command="{Binding DataContext.IncreaseReturnCommand, ElementName=lvItems}" Opacity="0.9"/>
<Button Grid.Row="1" Content="-" HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Grid.Column="2" Margin="0,0,0,-100" Height="100" FontSize="48" Style="{StaticResource NumUpDownButtonStyle}" Visibility="{Binding ElementName=lvItems, Path=DataContext.SelectedItem, ConverterParameter=Selected, Converter={StaticResource SelectionConverter}}" Command="{Binding DataContext.DecreaseReturnCommand, ElementName=lvItems}" Opacity="0.9"/>
<Button Grid.Row="1" Content="+" HorizontalAlignment="Stretch" VerticalAlignment="Top" Grid.Column="3" Height="100" Margin="0,-100,0,0" FontSize="48" Style="{StaticResource NumUpDownButtonStyle}" Visibility="{Binding ElementName=lvItems, Path=DataContext.SelectedItem, ConverterParameter=Selected, Converter={StaticResource SelectionConverter}}" Command="{Binding DataContext.IncreaseMildewCommand, ElementName=lvItems}" Opacity="0.9"/>
<Button Grid.Row="1" Content="-" HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Grid.Column="3" Margin="0,0,0,-100" Height="100" FontSize="48" Style="{StaticResource NumUpDownButtonStyle}" Visibility="{Binding ElementName=lvItems, Path=DataContext.SelectedItem, ConverterParameter=Selected, Converter={StaticResource SelectionConverter}}" Command="{Binding DataContext.DecreaseMildewCommand, ElementName=lvItems}" Opacity="0.9"/>
<Button Grid.Row="1" Content="+" HorizontalAlignment="Stretch" VerticalAlignment="Top" Grid.Column="4" Height="100" Margin="0,-100,0,0" FontSize="48" Style="{StaticResource NumUpDownButtonStyle}" Visibility="{Binding ElementName=lvItems, Path=DataContext.SelectedItem, ConverterParameter=Selected, Converter={StaticResource SelectionConverter}}" Command="{Binding DataContext.IncreaseCreditCommand, ElementName=lvItems}" Opacity="0.9"/>
<Button Grid.Row="1" Content="-" HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Grid.Column="4" Margin="0,0,0,-100" Height="100" FontSize="48" Style="{StaticResource NumUpDownButtonStyle}" Visibility="{Binding ElementName=lvItems, Path=DataContext.SelectedItem, ConverterParameter=Selected, Converter={StaticResource SelectionConverter}}" Command="{Binding DataContext.DecreaseCreditCommand, ElementName=lvItems}" Opacity="0.9"/>-->
</Grid>
</DataTemplate>
Style:
<Style x:Key="ReturnDataListViewItemStyle" TargetType="ListViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<ListViewItemPresenter x:Name="listViewItemPresenter" d:DesignWidth="938.908" d:DesignHeight="103.083"
ContentMargin="0"
DragOpacity="{ThemeResource ListViewItemDragThemeOpacity}"
DisabledOpacity="{ThemeResource ListViewItemDisabledThemeOpacity}"
HorizontalContentAlignment="Stretch"
Padding="0"
PointerOverBackgroundMargin="1"
ReorderHintOffset="{ThemeResource ListViewItemReorderHintThemeOffset}"
SelectionCheckMarkVisualEnabled="False"
SelectedBorderThickness="0"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
Margin="15,0,0,0"
SelectedForeground="Black"
SelectedPointerOverBackground="{StaticResource OrangeBackground}"
SelectedPointerOverBorderBrush="{StaticResource OrangeBackground}"
SelectedBackground="{StaticResource OrangeBackground}"
DataContext="{Binding SelectedItem}"
Content="{Binding Mode=OneWay}"
ContentTransitions="{TemplateBinding ContentTransitions}"
PlaceholderBackground="{StaticResource BackgroundGray}">
</ListViewItemPresenter>
</ControlTemplate>
</Setter.Value>
</Setter>
<!--<Setter Property="ContentTemplate" Value="{StaticResource ReturnDataTemplate}"/>-->
</Style>
In the Code behind of the XAML Page, I added the behavior of the ScrollViewer:
private void lvItems_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
SetScrollViewer();
}
private async void SetScrollViewer()
{
if (lvItems.SelectedItem == null)
return;
var item = lvItems.SelectedItem;
var listViewItem = (FrameworkElement)lvItems.ContainerFromItem(item);
if (listViewItem == null)
{
lvItems.ScrollIntoView(item);
}
while (listViewItem == null)
{
await Task.Delay(1);
listViewItem = (FrameworkElement)lvItems.ContainerFromItem(item);
}
var topLeft =
listViewItem
.TransformToVisual(lvItems)
.TransformPoint(new Point()).Y;
var lvih = listViewItem.ActualHeight;
var lvh = lvItems.ActualHeight;
var desiredTopLeft = (lvh - lvih) / 2.0;
var desiredDelta = topLeft - desiredTopLeft;
// Calculations relative to the ScrollViewer within the ListView
var scrollViewer = lvItems.GetFirstDescendantOfType<ScrollViewer>();
var currentOffset = scrollViewer.VerticalOffset;
var desiredOffset = currentOffset + desiredDelta;
//scrollViewer.ScrollToVerticalOffset(desiredOffset);
// better yet if building for Windows 8.1 to make the scrolling smoother use:
scrollViewer.ChangeView(null, desiredOffset, null);
}
Related
I'm trying to get an item in ListView in WPF when user doesn't select an item by clicking on it but the user taps on it.
Is there a way to achieve this in WPF ListView.
ListView dataSource is filled by a dynamic collection in code-behind.
I'm getting a null object when user taps on it.
Item selectedItem = (Item)lv_CartItems.SelectedItem;
this is how my data-template looks like for listview.
<ListView.ItemTemplate>
<DataTemplate>
<Viewbox>
<Grid Width="230" Height="110" >
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width=".1*" />
<ColumnDefinition />
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition Width=".5*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="2*" />
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Border BorderBrush="LightGray" BorderThickness="1"
Grid.Row="0" Grid.Column="0"
Grid.ColumnSpan="6" Grid.RowSpan="3" >
</Border>
<Viewbox Grid.Row="0" >
<Image Name="img_ItemImage"
Source="{Binding Image, Mode=TwoWay }"
Width="20" Height=" 25" />
</Viewbox>
<Viewbox Grid.Column="2" Grid.ColumnSpan="3" VerticalAlignment="Top" >
<TextBlock Name="lbl_ItemName" TextWrapping="Wrap" Width="180" Foreground="Gray"
Text="{Binding Name , Mode=TwoWay }" Tag="{Binding SKU_No,Mode=TwoWay}" >
</TextBlock>
</Viewbox>
<Viewbox Grid.Row="1" Margin="10,0" VerticalAlignment="Top" >
<TextBlock Foreground="Gray" >Qty:</TextBlock>
</Viewbox>
<Viewbox Grid.Row="2" Margin="0,0" VerticalAlignment="Top" >
<StackPanel Orientation="Horizontal" >
<Button Name="btn_Minus" FontWeight="ExtraBold" Padding="0" Width="12"
Resources="{StaticResource cartitembutton}" Click="btn_Minus_Click" >
<Image Source="/Resources\Icons\minus.png" ></Image>
</Button>
<Border BorderThickness="1" Margin="2,0" Width="13" CornerRadius="2" BorderBrush="LightGray" >
<TextBlock Name="lbl_Quantity" FontWeight="Bold" Foreground="Gray"
HorizontalAlignment="Center" VerticalAlignment="Center"
Text="{Binding Quantity , Mode=TwoWay }">
</TextBlock>
</Border>
<Button Name="btn_Increment" FontWeight="ExtraBold" Width="12"
Resources="{StaticResource cartitembutton}"
Padding="0"
Click="btn_Increment_Click">
<Image Source="/Resources\Icons\union_10.png" ></Image>
</Button>
</StackPanel>
</Viewbox>
<Viewbox Grid.Row="1" Grid.Column="2" Margin="5,0"
HorizontalAlignment="Left" Grid.ColumnSpan="3" >
<TextBlock Name="lbl_Price" FontWeight="DemiBold"
Text="{Binding Price , Mode=TwoWay}" ></TextBlock>
</Viewbox>
<Viewbox Grid.Row="2" Grid.Column="2" Grid.ColumnSpan="3"
VerticalAlignment="Top" Margin="0,0" >
<TextBlock Name="lbl_Appearence"
Text="{Binding Appearance , Mode=TwoWay }"
TextWrapping="Wrap" Foreground="Gray" Width="210" >
</TextBlock>
</Viewbox>
<Viewbox Grid.Column="5" HorizontalAlignment="Center" VerticalAlignment="Top" Margin="2,2"
>
<Button Name="btn_DeleteItem"
Click="btn_DeleteItem_Click"
Resources="{StaticResource cartitembutton}" >
<Image Source="/Resources/Icons/delete.png" ></Image>
</Button>
</Viewbox>
</Grid>
</Viewbox>
</DataTemplate>
</ListView.ItemTemplate>
You should use data binding to retrieve the selected item. The source property will be automatically updated when the ListView.SelectedItem changes.
Touch is handled the same way as click is handled. The framework converts touch events to mouse events.
I noticed that you wrapped every element into a ViewBox. That is not necessary and will only degrade performance. When the elements are hosted inside a Grid they will resize automatically by default. Exceptions are elements that need an initial size like Shape or Image. But since the item containers won't resize themselves, the content of the containers won't resize too.
To force all elements to occupy max horizontal space you can set a Style that targets the item container:
<ListView.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment"
Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
MainWindow.xaml.cs
public partial class MainWindow : Window
{
public static readonly DependencyProperty ItemsProperty = DependencyProperty.Register(
"Items",
typeof(ObservableCollection<Item>),
typeof(MainWindow),
new PropertyMetadata(default(ObservableCollection<Item>)));
public ObservableCollection<Item> Items
{
get => (ObservableCollection<Item>) GetValue(MainWindow.ItemsProperty);
set => SetValue(MainWindow.ItemsProperty, value);
}
public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register(
"SelectedItem",
typeof(Item),
typeof(MainWindow),
new PropertyMetadata(default(Item), MainWindow.OnSelectedItemChanged));
public Item SelectedItem
{
get => (Item) GetValue(MainWindow.SelectedItemProperty);
set => SetValue(MainWindow.SelectedItemProperty, value);
}
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
this.Items = new ObservableCollection<Item>();
// Initialize data source
CreateItems();
}
// Property changed callback of the SelectedItem property
private static void OnSelectedItemChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// Reference to instance members in a class scope
var _this = d as MainWindow;
if (e.NewValue is ItemCollection selectedItem)
{
// Handle currently selected item
}
}
}
MainWindow.xaml
<Window>
<ListView ItemsSource="{Binding Items}"
SelectedItem="{Binding SelectedItem}" />
</Window>
I have an ItemsControl with DataTemplate in my Page.Xaml and the code is like below:
<ItemsControl x:Name="chatUI" VerticalAlignment="Bottom">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid x:Name="myGrid" Width="340" Background="{Binding Background}" HorizontalAlignment="{Binding GridHorizontalAlign}" Margin="10,0,10,10" MinHeight="45" BorderBrush="#FF003A4F" BorderThickness="0,0,0,2">
<Polygon Visibility="{Binding RightVisibility}" Fill="{Binding Background}" Points="0,0 5,6, 0,12" VerticalAlignment="Top" HorizontalAlignment="Right" Margin="0,0,-5,0" />
<Polygon Visibility="{Binding LeftVisibility}" Fill="{Binding Background}" Points="5,0 0,6, 5,12" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="-5,0,0,0" />
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Text="{Binding Text}" TextWrapping="Wrap" FontSize="15" FontFamily="Segoe UI" Foreground="White" Margin="10,10,10,0"/>
<TextBlock Grid.Row="1" Text="{Binding Time}" TextWrapping="Wrap" FontSize="11" FontFamily="Segoe UI" Foreground="LightGray" Margin="10,0,10,5" VerticalAlignment="Bottom" TextAlignment="Right"/>
</Grid>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
What I need right now is getting Text which is bound to the TextBlock when I right click on the grid named myGrid. How is that possible in C#?
We can add the RightTapped event of the Grid, it will be fired when you right click the Grid.
In the RightTapped event we can use Grid.Children to get the collection of child elements of the Grid. That we can get the Grid in the root Grid that named myGrid. That we can use the Grid.Children to get the TextBlock in the Grid.
For example:
private async void myGrid_RightTapped(object sender, RightTappedRoutedEventArgs e)
{
var RightTapGrid = sender as Grid;
var childernElements = RightTapGrid.Children;
foreach (var item in childernElements)
{
var grid = item as Grid;
if (grid != null)
{
var itemchildernElements = grid.Children;
foreach (var text in itemchildernElements)
{
var textBlock = text as TextBlock;
var dialog = new ContentDialog()
{
Title = textBlock.Text,
MaxWidth = this.ActualWidth
};
dialog.PrimaryButtonText = "OK";
dialog.SecondaryButtonText = "Cancel";
await dialog.ShowAsync();
break;
}
}
}
}
If you get your Binding Data from Class called ClassName
You can try this code
XAML:
<ListView x:Name="chatUI" VerticalAlignment="Bottom" SelectionChanged="chatUI_SelectionChanged">
<ListView.ItemTemplate>
<DataTemplate>
<Grid x:Name="myGrid" Width="340" Background="{Binding Background}" HorizontalAlignment="{Binding GridHorizontalAlign}" Margin="10,0,10,10" MinHeight="45" BorderBrush="#FF003A4F" BorderThickness="0,0,0,2">
<Polygon Visibility="{Binding RightVisibility}" Fill="{Binding Background}" Points="0,0 5,6, 0,12" VerticalAlignment="Top" HorizontalAlignment="Right" Margin="0,0,-5,0" />
<Polygon Visibility="{Binding LeftVisibility}" Fill="{Binding Background}" Points="5,0 0,6, 5,12" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="-5,0,0,0" />
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Text="{Binding Text}" TextWrapping="Wrap" FontSize="15" FontFamily="Segoe UI" Foreground="White" Margin="10,10,10,0"/>
<TextBlock Grid.Row="1" Text="{Binding Time}" TextWrapping="Wrap" FontSize="11" FontFamily="Segoe UI" Foreground="LightGray" Margin="10,0,10,5" VerticalAlignment="Bottom" TextAlignment="Right"/>
</Grid>
</Grid>
</DataTemplate>
</Listview.ItemTemplate>
And add SelectionChanged Event :
private void chatUI_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ListView view = (ListView)sender;
//Get Selected Item
ClassName class = view.SelectedItem as ClassName;
string path = class.Text;
// Now we have Text of selected item in Listview
}
I have a data input form where i have textboxes,comboboxes and datepickers. I want to Bind comboboxes to the DB column so that users select the correct value for insertion. I have attached the viewmodel class and XAML code. In the viewmodel code "private void GetSW()" - this gets all the list of the entity class and "private void addSW()" this adds the record to the DB, Except the combobox binding everything works fine. in XAML i have binded combobox like this but this give blank combobox, please help what i am missing. I researched many topics on this forum but didn't find any solution
<ComboBox x:Name="PSW" Grid.Column="3" Grid.Row="2" ItemsSource="{Binding newSW.PreviousSW}" HorizontalAlignment="Left" VerticalAlignment="Top" Width="100" Height="20"/>
Its a ViewModel Code
using BusinessEntities;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using MUDB.Services;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
namespace MUDB.Ui.Logic
{
public class SoftwareVersionListViewModel:ViewModelBase
{
private bool enableRowDetails=false;
public bool EnagleRowDetails
{
get { return enableRowDetails; }
set {
enableRowDetails = value;
RaisePropertyChanged();
}
}
public SoftwareVersionListViewModel()
{
SaveSW = new RelayCommand(addSW);
//savecommand = new RelayCommand(addprod);
GetSW();
newSW = new SoftwareDefEntity();
EditSW = new RelayCommand(() => {
EnagleRowDetails = true;
MessageBox.Show("Edit button clicked!!");});
//SWList = new SoftwareDefEntity(); //Initializing the object of the Entity class
}
public List<SoftwareDefEntity> SWentities
{
get;
set;
}
private SoftwareDefEntity _selectedsw;
public SoftwareDefEntity Selectedsw
{
get { return _selectedsw; }
set
{
_selectedsw = value; //This will get all the values of that particular Selected row that are defined in the entity class
EnagleRowDetails = false; //Reset boolean value EnagleRowDetails, so that the selected rowdetails are disabled until Edit button is not clicked.
//ShowView();
}
}
public RelayCommand SaveSW { get; private set; }
public RelayCommand EditSW { get; private set; }
public SoftwareDefEntity newSW { get; private set; }
private void ShowView()
{
//cUSTOM METHODS
}
private void GetSW() // Method that reads the data from the service layer
{
SWDefService obj = new SWDefService();
SWentities = obj.getSW() ; //getSW is the method refered in Service layer
}
private void addSW()
{
SWDefService obj = new SWDefService();
obj.addSW(newSW); //newproduct object will hold the value of the binded control, in XAML its binded like this "{Binding newproduct.ProductName(ProductName is the field name in the entityclass/DB table)}"
newSW = new SoftwareDefEntity();
}
}
}
This is the XAML Code
<UserControl x:Class="MUDB.Ui.CreateSW"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MUDB.Ui"
xmlns:converter="clr-namespace:MUDB.Ui.Logic.Converters;assembly=MUDB.Ui.Logic"
xmlns:enums="clr-namespace:MUDB.Ui.Logic.Enums;assembly=MUDB.Ui.Logic"
mc:Ignorable="d" Height="Auto" Width="Auto"
DataContext="{Binding SoftwareVersionList,Source={StaticResource Locator}}" >
<UserControl.Resources>
<converter:RadioButtonToBooleanConverter x:Key="RadioButtonToBooleanConverter" />
</UserControl.Resources>
<Grid>
<Border Background="#90000000" Visibility="{Binding Visibility}">
<Border BorderBrush="Black" BorderThickness="1" Background="White"
CornerRadius="10,0,10,0" VerticalAlignment="Center"
HorizontalAlignment="Center">
<Border.BitmapEffect>
<DropShadowBitmapEffect Color="Black" Opacity="0.5" Direction="270" ShadowDepth="0.7" />
</Border.BitmapEffect>
<Grid Margin="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition Height="25"/>
<RowDefinition Height="30"/>
<RowDefinition Height="25"/>
<RowDefinition Height="30"/>
<RowDefinition Height="25"/>
<RowDefinition Height="30"/>
<RowDefinition Height="100"/>
<RowDefinition Height="40"/>
<RowDefinition Height="40"/>
<RowDefinition Height="40"/>
</Grid.RowDefinitions>
<Label Content="Create New Software Version" Grid.Column="0" Grid.Row="0" Foreground="White" Background="black"
HorizontalAlignment="Stretch" VerticalAlignment="Center" Grid.ColumnSpan="3" />
<Label Content="ECU" Grid.Column="0" Grid.Row="1" Foreground="Black" HorizontalAlignment="Left"
VerticalAlignment="Bottom" />
<Label Content="Software Name" Grid.Column="1" Grid.Row="1" Foreground="Black" HorizontalAlignment="Left"
VerticalAlignment="Bottom" />
<Label Content="Previous Software" Grid.Column="2" Grid.Row="1" Foreground="Black" HorizontalAlignment="Left"
VerticalAlignment="Bottom" />
<Label Content="Request Freeze Date" Grid.Column="0" Grid.Row="3" Foreground="Black" HorizontalAlignment="Left"
VerticalAlignment="Bottom" />
<Label Content="Request Freeze Status" Grid.Column="1" Grid.Row="3" Foreground="Black" HorizontalAlignment="Left"
VerticalAlignment="Bottom" />
<Label Content="Software Freeze Date" Grid.Column="0" Grid.Row="5" Foreground="Black" HorizontalAlignment="Left"
VerticalAlignment="Center" />
<Label Content="Software Freeze Status" Grid.Column="1" Grid.Row="5" Foreground="Black" HorizontalAlignment="Left"
VerticalAlignment="Center" />
<Label Content="Comments" Grid.Column="0" Grid.Row="7" Foreground="Black" HorizontalAlignment="Left"
VerticalAlignment="Center" />
<ComboBox x:Name="ECU" Grid.Column="0" Grid.Row="2" Text="{Binding newSW.ECU}" Margin="10 0 0 0" HorizontalAlignment="Left" VerticalAlignment="Top" Width="80" Height="Auto">
<ComboBoxItem Name="cbi1">ACM</ComboBoxItem>
<ComboBoxItem Name="cbi2">MCM</ComboBoxItem>
</ComboBox>
<TextBox x:Name="SW" Grid.Column="1" Grid.Row="2" Text="{Binding newSW.SoftwareName}" HorizontalAlignment="Left" VerticalAlignment="Top" Height="Auto" Width="150" />
<ComboBox x:Name="PSW" Grid.Column="3" Grid.Row="2" ItemsSource="{Binding PreviousSW}" HorizontalAlignment="Left" VerticalAlignment="Top" Width="100" Height="20"/>
<DatePicker Grid.Column="0" Grid.Row="4" Margin="10 0 0 0" HorizontalAlignment="Left" VerticalAlignment="top" SelectedDate="{Binding newSW.Req_Freeze_Date}" Height="Auto" Width="Auto"/>
<DatePicker Grid.Column="0" Grid.Row="6" Margin="10 0 0 0" HorizontalAlignment="Left" VerticalAlignment="top" SelectedDate="{Binding newSW.SW_Freeze_Date}" Height="Auto" Width="Auto"/>
<RadioButton Content="Yes" GroupName="ReQstat" IsChecked="{Binding newSW.Req_Freeze_Status, Mode=OneWayToSource, Converter={StaticResource RadioButtonToBooleanConverter}, ConverterParameter={x:Static enums:RadioSelectionEnum.Yes}}" Style="{StaticResource AccentRadioButton}" Grid.Column="1" Grid.Row="4" HorizontalAlignment="Left" VerticalAlignment="Top" Height="14" Width="Auto"/>
<RadioButton Content="No" GroupName="ReQstat" IsChecked="{Binding newSW.Req_Freeze_Status, Mode=OneWayToSource, Converter={StaticResource RadioButtonToBooleanConverter}, ConverterParameter={x:Static enums:RadioSelectionEnum.No}}" Style="{StaticResource AccentRadioButton}" Grid.Column="1" Grid.Row="4" Margin="60 0 0 0" HorizontalAlignment="Left" VerticalAlignment="Top" Height="Auto" Width="Auto"/>
<RadioButton Content="Yes" GroupName="SWstat" IsChecked="{Binding newSW.SW_Freeze_Status, Mode=OneWayToSource, Converter={StaticResource RadioButtonToBooleanConverter}, ConverterParameter={x:Static enums:RadioSelectionEnum.Yes}}" Style="{StaticResource AccentRadioButton}" Grid.Column="1" Grid.Row="6" HorizontalAlignment="Left" VerticalAlignment="Top" Height="Auto" Width="Auto"/>
<RadioButton Content="No" GroupName="SWstat" IsChecked="{Binding newSW.SW_Freeze_Status, Mode=OneWayToSource, Converter={StaticResource RadioButtonToBooleanConverter}, ConverterParameter={x:Static enums:RadioSelectionEnum.No}}" Style="{StaticResource AccentRadioButton}" Grid.Column="1" Grid.Row="6" Margin="60 0 0 0" HorizontalAlignment="Left" VerticalAlignment="Top" Height="Auto" Width="Auto"/>
<TextBox x:Name="CommenttextBox" Grid.Column="1" Grid.Row="7" HorizontalAlignment="Left" Height="69" TextWrapping="WrapWithOverflow" VerticalAlignment="Center" Text="{Binding Comment}" Width="170" Margin="4.4,2.2,0,0" />
<UniformGrid Grid.Row="9" Margin="2" Columns="2" HorizontalAlignment="Stretch"
VerticalAlignment="Center" Height="Auto">
<Button x:Name="SaveButton" Command="{Binding SaveSW}" Content="Save" Height="27" />
<Button x:Name="CloseButton" Click="CloseButton_Click" Content="Close" Height="26" />
</UniformGrid>
</Grid>
</Border>
</Border>
</Grid>
</UserControl>
I guess you want to display the list of SoftwareDefEntity objects in your ComboBox.
Bind to the SWentities property then:
<ComboBox x:Name="PSW" Grid.Column="3" Grid.Row="2" ItemsSource="{Binding SWentities}" DisplayMemberPath="Name" ... />
And raise the PropertyChanged event in its setter of this property:
private List<SoftwareDefEntity> _swEntities;
public List<SoftwareDefEntity> SWentities
{
get { return _swEntities; }
set { _swEntities = value; RaisePropertyChanged(); }
}
This is the code to bind the data to combobox. i did not add any of other controls since those are working fine at your place. Observable collection is easy way to bind combobox .
Here is your View Model..
public class SoftwareVersionListViewModel : ViewModelBase
{
public SoftwareVersionListViewModel()
{
GetSW();
}
//Define the observable collection
private ObservableCollection<SoftwareDefEntity> _SWmappings2 = new ObservableCollection<SoftwareDefEntity>();
//here is your Entity list
public List<SoftwareDefEntity> SWentities
{
get;
set;
}
// Obeservable collection property for access
public ObservableCollection<SoftwareDefEntity> SWmappings2
{
get { return _SWmappings2; }
set
{
_SWmappings2 = value;
OnPropertyChanged("appeventmappings2");
}
}
/// <summary>
/// load the combobox
/// </summary>
private void GetSW() // Method that reads the data from the service layer
{
SWDefService obj = new SWDefService();
SWentities = obj.getSW(); //getSW is the method refered in Service layer
SWentities.ForEach(_SWmappings2.Add);
}
}
and Xaml...
<ComboBox x:Name="ComboBox" ItemsSource="{Binding SWmappings2, UpdateSourceTrigger=PropertyChanged}" DisplayMemberPath="PreviousSW" SelectedItem="{Binding PreviousSW, Mode=TwoWay}" Grid.Row="0" >
</ComboBox>
I'm trying to update the controls present on my Main Window based on the listviewitem selected by the user, but when the listviewitem selection is changed the controls do not update.
I used this post as reference How to dynamically change a WPF control's template using a checkbox?
EDIT: I initially used ContentTemplate but changed this to DataTemplate based on suggestions, however it still is not updating
The XMAL for my Main Window is
<Window.Resources>
<DataTemplate x:Key="Default">
<Grid Margin="20,280,0,0" />
</DataTemplate>
<DataTemplate x:Key="ERAFileSelect">
<Border BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Left" Height="218" Margin="20,280,0,0" VerticalAlignment="Top" Width="257" CornerRadius="15">
<Grid Name="grdFileSelect">
<Label x:Name="lblProcessContent" Content="Drag File or Manually Select File" HorizontalAlignment="Center" VerticalAlignment="Top" Width="257" HorizontalContentAlignment="Center"/>
<TextBox x:Name="txtEraFileName" HorizontalAlignment="Left" Height="23" Margin="10,80,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="235"/>
<Button x:Name="btnSelectFiles" Content="Manually Select File(s)" HorizontalAlignment="Left" Margin="10,161,0,0" VerticalAlignment="Top" Width="235" Height="45"/>
</Grid>
</Border>
</DataTemplate>
<DataTemplate x:Key="FCSFileSelect">
<Border BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Left" Height="218" Margin="20,280,0,0" VerticalAlignment="Top" Width="257" CornerRadius="15">
<Grid Name="grdFileSelect">
<Label x:Name="lblProcessContent" Content="Drag File or Manually Select Files" HorizontalAlignment="Center" VerticalAlignment="Top" Width="257" HorizontalContentAlignment="Center"/>
<TextBox x:Name="txtFCSFileName_TQ02" HorizontalAlignment="Left" Height="23" Margin="10,40,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="174"/>
<Button x:Name="btnSelectFiles_TQ02" Content="Select" HorizontalAlignment="Left" Margin="189,37,0,0" VerticalAlignment="Top" Width="56" Height="28"/>
<TextBox x:Name="txtFCSFileName_TQ11" HorizontalAlignment="Left" Height="23" Margin="10,105,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="174"/>
<Button x:Name="btnSelectFiles_TQ11" Content="Selec" HorizontalAlignment="Left" Margin="189,100,0,0" VerticalAlignment="Top" Width="56" Height="28"/>
<TextBox x:Name="txtFCSFileName_TQ16" HorizontalAlignment="Left" Height="23" Margin="10,170,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="174"/>
<Button x:Name="btnSelectFiles_TQ16" Content="Select" HorizontalAlignment="Left" Margin="189,165,0,0" VerticalAlignment="Top" Width="56" Height="28"/>
</Grid>
</Border>
</DataTemplate>
</Window.Resources>
<Grid Margin="0,0,2,0">
<GroupBox x:Name="gbxProgress" Header="Progress" HorizontalAlignment="Left" Margin="298,105,0,0" VerticalAlignment="Top" Height="445" Width="462" Foreground="Black">
<ListBox x:Name="lbxProgress" HorizontalAlignment="Left" Height="408" Margin="10,10,0,0" VerticalAlignment="Top" Width="431" Foreground="Black" IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding Progress.Message}" />
</GroupBox>
<Button x:Name="btnStart" Content="Start" HorizontalAlignment="Left" Margin="20,513,0,0" VerticalAlignment="Top" Width="100" Height="37" IsEnabled="{Binding Properties.StartButtonEnabled}" Click="btnStart_Click"/>
<Button x:Name="btnCancel" Content="Cancel" HorizontalAlignment="Left" Margin="177,513,0,0" VerticalAlignment="Top" Width="100" Height="37"/>
<Border BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Left" Height="70" Margin="20,21,0,0" VerticalAlignment="Top" Width="740" CornerRadius="15">
<Grid>
<Image HorizontalAlignment ="Left" Margin="10" Height="50" Width="50" VerticalAlignment="Center" Source="/Lib/Icons/User.png" />
<TextBlock Name="txtUser" FontSize="20" Height="30" Width="200" Foreground="Red" HorizontalAlignment="Left" Margin="78,19,0,19"/>
<Image HorizontalAlignment ="Left" Margin="443,8,0,10" Height="50" Width="50" VerticalAlignment="Center" Source="Lib/Icons/Watch.png" />
<TextBlock x:Name="txtRunTime" FontSize="20" Height="30" Width="200" Foreground="Red" HorizontalAlignment="Left" Margin="519,19,0,19" Text="{Binding AppRunTime.TimeElapsed}" />
</Grid>
</Border>
<Border BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Left" Height="144" Margin="20,119,0,0" VerticalAlignment="Top" Width="257" CornerRadius="15">
<Grid>
<Label x:Name="lblProcessSelection" Content="Process Selection" HorizontalAlignment="Center" VerticalAlignment="Top" Width="257" HorizontalContentAlignment="Center"/>
<ListView x:Name="lvProcessSelection" HorizontalAlignment="Left" Height="93" Margin="10,30,0,0" VerticalAlignment="Top" Width="235" BorderThickness="0" SelectionChanged="lvProcessSelection_SelectionChanged">
<ListViewItem Name="itmERA" Content="Expense Reserve Automation"/>
<ListViewItem Name="itmFCS" Content="Financial Close Status"/>
<ListViewItem Name="itmPEL" Content="Peel"/>
</ListView>
</Grid>
</Border>
<ContentControl DataContext="{Binding Properties}" Content="{Binding}">
<ContentControl.Style>
<Style TargetType="ContentControl">
<Setter Property="ContentTemplate" Value="{StaticResource ERAFileSelect}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding SelectedProcess}" Value="Expense Reserve Automation">
<Setter Property="ContentTemplate" Value="{StaticResource ERAFileSelect}" />
</DataTrigger>
<DataTrigger Binding="{Binding SelectedProcess}" Value="Financial Close Status">
<Setter Property="ContentTemplate" Value="{StaticResource FCSFileSelect}" />
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</Grid>
ViewModel Code is
public class MainWindowModel
{
public ApplicationRunTime AppRunTime { get; set; }
public LogMessage Progress { get; set; }
public MainWindowProperties Properties { get; set; }
public MainWindowModel()
{
AppRunTime = new ApplicationRunTime();
Progress = new LogMessage();
Properties = new MainWindowProperties();
Properties.StartButtonEnabled = false;
}
}
With the MainWindowProperties class
public class MainWindowProperties
{
public bool StartButtonEnabled { get; set; }
public string SelectedProcess { get; set; }
}
And within my MainWindow Constructor I have set the DataContext
mainWindowModel = new MainWindowModel();
this.DataContext = mainWindowModel;
When the selection from lvProcessSelection is changed the following code is executed
if (lvProcessSelection.SelectedItems.Count > 0)
{
mainWindowModel.Properties.SelectedProcess = ((ListViewItem)lvProcessSelection.SelectedItem).Content.ToString();
}
else
{
mainWindowModel.Properties.SelectedProcess = string.Empty;
}
This will update SelectedProcess within my ViewModel with either "Expense Reserve Automation" or "Financial Close Status"
I know the DataContext is set correctly for my ViewModel (but may not be for the ContentControl) as I am able to update lbxProgress with new messages and update txtRunTime with the application RunTime
However when I change the selection on lvProcessSelection nothing happens; the default controls of ERAFileSelect remains.
Could anybody point me in the right direction on how to solve this?
Could anybody point me in the right direction on how to solve this?
Your MainWindowProperties class should implement the INotifyPropertyChanged interface and raise change notifications whenever the SelectedProcess property is set to a new value:
public class MainWindowProperties : INotifyPropertyChanged
{
public bool StartButtonEnabled { get; set; }
private string _selectedProcess;
public string SelectedProcess
{
get { return _selectedProcess; }
set { _selectedProcess = value; NotifyPropertyChanged(); }
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
Please refer to MSDN for more information about this common interface: https://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged(v=vs.110).aspx
Every view model/model that you bind to must implement this interface and raise change notifications for any target value in the view to be updated.
Why you are not using Data template? Data template will work in this scenario.
I have a xaml page with a reaction form. I load this reaction dynamicly in a listbox but the button that I use on this reaction doesn't work. I load the reactions as objects in the listbox.
This is the reaction
<Grid x:Name="LayoutRoot" VerticalAlignment="Stretch">
<Border Background="DarkGray" CornerRadius="10" Width="400">
<StackPanel Orientation="Vertical" Width="400" Background="DarkGray" Margin="10,10,10,10">
<Grid>
<TextBlock HorizontalAlignment="Left" Name="tbDateCreated" Text="tbDateCreated" VerticalAlignment="Stretch" FontSize="15" TextWrapping="NoWrap" FontFamily="Segoe WP" Width="152" TextAlignment="Left" Foreground="White" Margin="190,0,0,0" />
<TextBlock HorizontalAlignment="Left" Name="tbTimeCreated" Text="tbTimeCreated" VerticalAlignment="Stretch" FontSize="15" TextWrapping="NoWrap" FontFamily="Segoe WP" Width="152" TextAlignment="Left" Foreground="White" Margin="270,0,-70,0" />
<TextBlock HorizontalAlignment="Left" Name="tbAuthor" Text="tbAuthor" VerticalAlignment="Stretch" FontSize="15" TextWrapping="NoWrap" FontFamily="Segoe WP" FontWeight="Bold" TextAlignment="Left" Margin="10,0,0,0" Width="158" Foreground="White" />
</Grid>
<TextBlock HorizontalAlignment="Stretch" Name="tbContent" Text="tbContent" VerticalAlignment="Stretch" FontSize="15" TextWrapping="Wrap" FontFamily="Segoe WP" TextAlignment="Left" Margin="10,5,20,0" Foreground="White" />
<Line Stretch="Fill" Stroke="Black" X1="0" X2="1" Y1="0" Y2="0" Margin="10,20,10,0" />
<Border Background="Gray" Width="90" Height="30" Margin="-290,10,0,0" CornerRadius="10">
<Button x:Name="reageer" BorderBrush="Gray" Background="Gray" Margin="-5,-12,0,0" Height="60" Width="100" FontSize="12" Click="Button_Click" Tap="reageer_Tap" Content="Reageer" VerticalContentAlignment="Top"/>
</Border>
</StackPanel>
</Border>
</Grid>
And this is the code to load the reaction with data.
public string DateCreated { get { return tbDateCreated.Text; } set { tbDateCreated.Text = value; } }
public string TimeCreated { get { return tbTimeCreated.Text; } set { tbTimeCreated.Text = value; } }
public string Author { get { return tbAuthor.Text; } set { tbAuthor.Text = value; } }
public string TextContent { get { return tbContent.Text; } set { tbContent.Text = value; } }
In the next page I load this reaction.
<ListBox Margin="0,0,0,20" Name="lbComments" VerticalAlignment="Top" IsHitTestVisible="False"/>
How can I use the button in my reaction to work on the page where the listbox is?