I have done opening the modal dialog in Wpf MVVM. But I am new to prism. I have tried the following code in MVVM. Now its working fine. But I want to do the same concept using prism with ribbon window. In the below code I have not used ribbon window, instead of ribbon window I used the button. please refer the below code,
MainWindow.xaml
<Window.Resources>
<DataTemplate DataType="{x:Type vm:ModalDialogViewModel}">
<view:ModalDialog />
</DataTemplate>
</Window.Resources>
<Grid>
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Center">
<Grid>
<Button
Width="150"
Height="25"
Margin="0,10,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Command="{Binding Path=LoadViewCommand}"
Content="Show Modal Dialog" />
</Grid>
</Grid>
<Grid Visibility="{Binding IsCloseModalWindow, Converter={StaticResource BooleanToVisibilityConverter}}">
<Border Background="#90000000">
<Border
HorizontalAlignment="Center"
VerticalAlignment="Center"
Background="White"
BorderBrush="Transparent"
BorderThickness="0"
CornerRadius="0">
<Border.BitmapEffect>
<DropShadowBitmapEffect
Direction="270"
Opacity="0.5"
ShadowDepth="0.7"
Color="Black" />
</Border.BitmapEffect>
<ContentControl Content="{Binding Path=CurrentViewModel}" />
</Border>
</Border>
</Grid>
</Grid>
MainWindowViewModel
public class MainWindowViewModel : ViewModelBase, ICloseWindow
{
private ICommand loadViewCommand;
private ViewModelBase _currentViewModel;
public ViewModelBase CurrentViewModel
{
get { return _currentViewModel; }
set
{
_currentViewModel = value;
this.OnPropertyChanged("CurrentViewModel");
}
}
private bool isCloseModalWindow = false;
public bool IsCloseModalWindow
{
get { return isCloseModalWindow; }
set { isCloseModalWindow = value; OnPropertyChanged("IsCloseModalWindow"); }
}
public MainWindowViewModel()
{
}
public ICommand LoadViewCommand => loadViewCommand ?? (loadViewCommand = new RelayCommand(showView, canShowView));
private void showView(object obj)
{
IsCloseModalWindow = true;
CurrentViewModel = new ModalDialogViewModel(new ModalDialogModel() { Name = "New Modal Window" }, this);
}
private bool canShowView(object obj)
{
return true;
}
public void closeWindow()
{
IsCloseModalWindow = false;
}
}
ModalDialog
<Grid MinWidth="300" Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid
Grid.Row="0"
MinHeight="30"
Background="SkyBlue">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button
Grid.Column="1"
Width="40"
Height="25"
Content="X"
BorderThickness="0"
Background="Transparent"
Foreground="White"
Margin="0,0,5,0"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Command="{Binding CancelCommand}"
CommandParameter="{Binding ElementName=modalDialog}"
ToolTip="Close" />
</Grid>
</Grid>
<Grid Grid.Row="1" Margin="15">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label
Grid.Row="0"
Grid.Column="0"
Content="Name"
Style="{StaticResource commonMargin}" />
<Label
Grid.Row="0"
Grid.Column="1"
Content=":"
Style="{StaticResource commonMargin}" />
<TextBox
Grid.Row="0"
Grid.Column="2"
Width="100"
Text="{Binding Path=Name}"
Style="{StaticResource commonTimerMargin}" />
</Grid>
<Grid
Grid.Row="2"
Margin="0,0,15,10"
HorizontalAlignment="Right">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Button
Grid.Column="0"
Width="80"
Height="30"
Margin="0,0,10,0"
Background="White"
Command="{Binding CancelCommand}"
CommandParameter="{Binding ElementName=modalDialog}"
Content="CANCEL" />
<Button
Grid.Column="1"
Width="80"
Height="30"
Background="SkyBlue"
Command="{Binding ApplyCommand}"
CommandParameter="{Binding ElementName=modalDialog}"
Content="APPLY"
Foreground="White" />
</Grid>
</Grid>
ModalDialogViewModel
public class ModalDialogViewModel : ViewModelBase
{
private ICommand cancelCommand;
public ModalDialogModel Model { get; private set; }
private ICloseWindow _closeWindow;
public ModalDialogViewModel(ModalDialogModel modalDialogModel, ICloseWindow closeWindow)
{
this.Model = modalDialogModel;
this._closeWindow = closeWindow;
}
public ICommand CancelCommand => cancelCommand ?? (cancelCommand = new RelayCommand(CloseWindow, CanCloseWindow));
private void CloseWindow(object obj)
{
_closeWindow.closeWindow();
}
private bool CanCloseWindow(object obj)
{
return true;
}
}
My Requirement is when user click the ribbon window button the modal dialog is open. The Shell window is a ribbon window. I have added HomeTab module and many other modules as separate class library.
You can do it like this in .xaml:
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:prism="http://prismlibrary.com/"
<i:Interaction.Triggers>
<prism:InteractionRequestTrigger SourceObject="{Binding PopUpDialogActionBinding}"> '<-- Here is your action binding
<prism:PopupWindowAction IsModal="True" CenterOverAssociatedObject="False">
<prism:PopupWindowAction.WindowStyle>
<Style TargetType="Window">
<Setter Property="Icon" Value="IconPath"/>
<Setter Property="Height" Value="400"/>
<Setter Property="Width" Value="400"/>
</Style>
</prism:PopupWindowAction.WindowStyle>
<prism:PopupWindowAction.WindowContent>
<views:YourCustomView /> ' <--- Put your view into the dialog
</prism:PopupWindowAction.WindowContent>
</prism:PopupWindowAction>
</prism:InteractionRequestTrigger>
</i:Interaction.Triggers>
<Grid>
...
</Grid>
I did it as in the example 28:
https://github.com/PrismLibrary/Prism-Samples-Wpf
Related
I've been working on a small tool for ISO integration and I decided to use WPF for the UI. I'm also doing my best to follow the MVVM pattern for future projects. For the main window, I decided to use WindowChrome so I could keep resizing with a restyled window, however, when I try to select a different view, it causes a exception. I tested it and it does work fine, but as soon as I try to bind the content to the templates content, it seems to cause issues with changing the current view.
Main window xaml:
<WindowChrome.WindowChrome>
<WindowChrome ResizeBorderThickness="{Binding ResizeBorderThickness}"
CaptionHeight="{Binding TitleHeight}" GlassFrameThickness="0"/>
</WindowChrome.WindowChrome>
<Window.Resources>
<Style TargetType="{x:Type local:OSToolWPF}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Window}">
<Border Padding="{Binding OuterMarginThickness}">
<Grid>
<Border CornerRadius="{Binding WindowCornerRadius}"
Background="{StaticResource BackgroundLightBrush}">
<Border.Effect>
<DropShadowEffect ShadowDepth="0" Opacity=".2"/>
</Border.Effect>
</Border>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="{Binding TitleHeightGridLength, FallbackValue=50}"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Border CornerRadius="10 10 0 0"
Background="{StaticResource BackgroundDarkBrush}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Viewbox Margin="25 0 0 0" HorizontalAlignment="Left">
<TextBlock Text="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Title}"/>
</Viewbox>
<StackPanel Grid.Column="1" Orientation="Horizontal">
<Button Style="{StaticResource ButtonBase}" Command="{Binding Minimize}" Width="50">
<Image Style="{StaticResource ControlImage}" Source="/Assets/Top/Minimize.png" Stretch="None"/>
</Button>
<Button Style="{StaticResource ButtonBase}" Command="{Binding Maximize}" Width="50">
<Image Style="{StaticResource ControlImage}" Source="/Assets/Top/Windowed.png" Stretch="None"/>
</Button>
<Button Style="{StaticResource ButtonBase}" Command="{Binding Close}" Width="50">
<Image Style="{StaticResource ControlImage}" Source="/Assets/Top/Close.png" Stretch="None"/>
</Button>
</StackPanel>
</Grid>
</Border>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="5*"/>
</Grid.ColumnDefinitions>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackPanel>
<Button Style="{StaticResource ButtonBase}" Tag="Registry" Command="{Binding Menu}"
Content="Registry" FontSize="20" Height="50" CommandParameter="{Binding
RelativeSource={RelativeSource Mode=Self}, Path=Tag}"/>
<Button Style="{StaticResource ButtonBase}" Tag="Services" Command="{Binding Menu}"
Content="Services" FontSize="20" Height="50" CommandParameter="{Binding
RelativeSource={RelativeSource Mode=Self}, Path=Tag}"/>
<Button Style="{StaticResource ButtonBase}" Tag="Visuals" Command="{Binding Menu}"
Content="Visuals" FontSize="20" Height="50" CommandParameter="{Binding
RelativeSource={RelativeSource Mode=Self}, Path=Tag}"/>
</StackPanel>
<Button Grid.Row="2" Style="{StaticResource ButtonBase}"
Content="Exit" FontSize="20" Command="{Binding Close}"
Height="50"/>
</Grid>
<Border Grid.Column="1">
<ContentControl Content="{TemplateBinding Content}"/>
<Border/>
</Grid>
</Grid>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<ContentControl Content="{Binding CurrentView}"/>
Main window view model (the data binding is done in xaml.cs since it needs a window):
public class OSToolViewModel : BaseViewModel
{
#region Private
private Window wWindow;
private object wCurrentView;
private int wOuterMarginSize = 10;
private int wWindowRadius = 15;
#endregion
public OSToolViewModel(Window window)
{
wWindow = window;
wWindow.StateChanged += (sender, e) =>
{
OnPropertyChanged(nameof(ResizeBorderThickness));
OnPropertyChanged(nameof(OuterMarginSize));
OnPropertyChanged(nameof(OuterMarginThickness));
OnPropertyChanged(nameof(WindowRadius));
OnPropertyChanged(nameof(WindowCornerRadius));
};
Menu = new BaseCommand(e => CurrentView = new ExpanderItemsList());
Minimize = new BaseCommand(e => wWindow.WindowState = WindowState.Minimized);
Maximize = new BaseCommand(e => wWindow.WindowState ^= WindowState.Maximized);
Close = new BaseCommand(e => CloseMessage());
}
#region Voids
private void CloseMessage()
{
if (DialogBox.Show("Would you like to exit?", "", wWindow.Title, DialogBoxButtons.YesNo) == DialogResult.Yes)
{
wWindow.Close();
}
}
#endregion
#region Commands
public BaseCommand Menu { get; set; }
public BaseCommand Minimize { get; set; }
public BaseCommand Maximize { get; set; }
public BaseCommand Close { get; set; }
#endregion
#region Public
public object CurrentView
{
get { return wCurrentView; }
set
{
if (value == wCurrentView)
return;
wCurrentView = value;
OnPropertyChanged(nameof(CurrentView));
}
}
public int ResizeBorder { get; set; } = 6;
public int OuterMarginSize
{
get
{
return wWindow.WindowState == WindowState.Maximized ? 0 : wOuterMarginSize;
}
set
{
wOuterMarginSize = value;
}
}
public int WindowRadius
{
get
{
return wWindow.WindowState == WindowState.Maximized ? 0 : wWindowRadius;
}
set
{
wWindowRadius = value;
}
}
public double TitleHeight { get; set; } = 50;
public Thickness ResizeBorderThickness { get { return new Thickness(ResizeBorder + OuterMarginSize); } }
public Thickness OuterMarginThickness { get { return new Thickness(OuterMarginSize); } }
public CornerRadius WindowCornerRadius { get { return new CornerRadius(WindowRadius); } }
public GridLength TitleHeightGridLength { get { return new GridLength(TitleHeight + ResizeBorder); } }
#endregion
}
The view I'm trying to bind to is a page, so I'm not sure if that would cause issues or not, but I've tried a lot of different combos and the combo I shared causes a exception. If I didn't bind to to the templated content, it would work fine. I'm baffled as to why this happens, and as a side note, the buttons in the window aren't cornered like they should be, so if you have a solution for this too, that would be much appreciated! Thank you and I hope you enjoy your day!
I just realized this issue was because of the fact I was using a Page rather than a UserControl. Switching the view to a UserControl solved the issue. Hopefully this helps if anyone else runs into this issue.
I am trying to make a button in a viewmodel recognize that a radio button in another view model (a UserControl that is activated on the first viewmodel) has been selected, thus enabling the button in the first viewmodel.
I have a UserControl AlbumsDisplayViewModel within my base view model BaseViewModel.
In BaseView XAML There's a button (OpenAlbum) which is supposed to be enabled when a radio button on the AlbumsDisplayView is selected (see CanOpenAlbum).
BaseView XAML:
<Canvas x:Name="cnvsInputWrapper" Background="LightGray"
Grid.Column="4" Grid.Row="1" Grid.RowSpan="4"
Margin="5">
<Canvas.OpacityMask>
<VisualBrush Visual="{Binding ElementName=maskRoundEdges}" />
</Canvas.OpacityMask>
<DockPanel Margin="15, 25">
<ContentControl x:Name="ActiveItem" />
</DockPanel>
</Canvas>
<!-- Action Buttons section -->
<Grid Grid.Row="3" Grid.Column="1" Grid.RowSpan="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="12" />
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="12" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="12" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="*" />
<RowDefinition Height="12" />
</Grid.RowDefinitions>
<Button Grid.Row="1" Grid.Column="1" x:Name="OpenAlbum"
IsEnabled="{Binding CanOpenAlbum}">
<StackPanel Orientation="Vertical">
<TextBlock>Open</TextBlock>
<TextBlock>Album</TextBlock>
</StackPanel>
</Button>
</Grid>
BaseViewModel C#:
public class BaseViewModel : Conductor<object>
{
private AlbumsDisplayViewModel m_vmAlbumsDisplay; // Initialized in another function.
public BaseViewModel()
{
}
public bool CanOpenAlbum() => (m_vmAlbumsDisplay != null) && (m_vmAlbumsDisplay.GetSelectedAlbum() != null);
public void OpenAlbum()
{
AlbumModel album = m_vmAlbumsDisplay.GetSelectedAlbum();
//ActivateItem(/*albumViewModel(album)*/);
}
}
AlbumsDisplayView XAML:
<ItemsControl x:Name="Albums" FlowDirection="LeftToRight"
Margin="10, 0">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type vms:AlbumViewModel}">
<StackPanel Orientation="Horizontal" Margin="0, 5">
<RadioButton GroupName="rdbtnAlbums"
IsChecked="{Binding IsSelected}" />
<!-- Album Details -->
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
AlbumsDisplayViewModel C#:
class AlbumsDisplayViewModel : Screen
{
private ObservableCollection<AlbumViewModel> m_albums;
public AlbumsDisplayViewModel()
{
}
public ObservableCollection<AlbumViewModel> Albums
{
get { return m_albums; }
set
{
m_albums = value;
NotifyOfPropertyChange(() => Albums);
}
}
public AlbumModel GetSelectedAlbum()
{
AlbumModel res = null;
foreach (var vmAlbum in Albums)
{
if (vmAlbum.IsSelected)
{
res = vmAlbum.Album;
break;
}
}
return res;
}
}
And last, AlbumViewModel C#:
class AlbumViewModel : Screen
{
private AlbumModel m_albumModel;
private bool m_isSelected;
public AlbumViewModel(AlbumModel albumModel)
{
m_albumModel = albumModel;
}
public AlbumModel Album
{
get { return m_albumModel; }
set
{
m_albumModel = value;
NotifyOfPropertyChange(() => Album);
}
}
public bool IsSelected
{
get { return m_isSelected; }
set
{
m_isSelected = value;
NotifyOfPropertyChange(() => IsSelected);
}
}
}
I expected that when IsSelected in AlbumViewModel is changed (when the user selects a radio button), the OpenAlbum button will be enabled, because CanOpenAlbum will return true, but I have realized that CanOpenAlbum wasn't even called for some reason. What do I need to do so CanOpenAlbum will be notified to be called whenever a radio button is selected?
After searching for an answer for a long time, I decided that it will be better to search for a better solution, instead of an answer. I've discovered that a ListBox element has a SelectedItem property, which eliminates the need for radio buttons.
Eventually, I replaced the ItemsControl with a ListBox, and I;m happy with the results.
AlbumDisplayView XAML (only this has changed):
<ScrollViewer x:Name="Scroller" Height="300"
FlowDirection="RightToLeft">
<ListBox x:Name="Albums" FlowDirection="LeftToRight"
Background="Transparent" Margin="10, 0"
BorderThickness="0" SelectedItem="{Binding SelectedAlbum}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type vms:AlbumViewModel}">
<StackPanel Orientation="Horizontal" Margin="0, 5">
<!-- Album Details -->
<StackPanel Orientation="Vertical">
<StackPanel Grid.Row="1" Grid.Column="1"
Orientation="Horizontal" Margin="12, 0">
<TextBlock Text="{Binding Album.Name}" />
<TextBlock Text=" - User#" />
<TextBlock Text="{Binding Album.OwnerID}" />
</StackPanel>
<TextBlock Text="{Binding Album.CreationDate}"
FontSize="12" Margin="12, 0" />
</StackPanel>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ListBox>
</ScrollViewer>
I'm learning wpf through mvvm.
My application consist of below logic.
Form which has a button that will add a selected components horizontally from Itemcontrol like textbox, combobox and rich textbox and a button whenever the button is clicked.
When the add button is clicked the specified set of components will be added in the line information dynamically.
2) Data will be inserted into the table after pressing the add info button.
3) The issue is after clicking the add info button, the components in the itemscontrol should be readonly. This is the place I'm struggling as of now.
Model.cs:
public class textboxModel
{
public string Text { get; set; }
public string lblText { get; set; }
public string isactive { get; set; }
public bool txtboxreadonly { get; set; }
}
public class ButtonDataModel
{
public string Content { get; set; }
public ICommand Command { get; set; }
public string column { get; set; }
public string isactive { get; set; }
public bool buttreadonly { get; set; }
}
ViewModel.cs:
public class viewmodel : notifyproperties
{
public Relaycommand Status { get; set; }
public Relaycommand AddCommand { get; set; }
public labelconversionOnPauseButtonclick pauseclick = new labelconversionOnPauseButtonclick();
public auditinformation auditid = new auditinformation();
public ButtonDataModel bdm = new ButtonDataModel();
public auditinformation adt
{
get { return auditid; }
set
{
if (value != auditid)
{
auditid = value;
OnPropertyChanged("adt");
}
}
}
public labelconversionOnPauseButtonclick res
{
get { return pauseclick; }
set
{
if (value != pauseclick)
{
pauseclick = value;
OnPropertyChanged("res");
}
}
}
public viewmodel()
{
Status = new Relaycommand(pauseclick.Statusdata);
AddCommand = new Relaycommand(o => auditid.addcommand());
}
}
public class auditinformation : notifyproperties
{
public Relaycommand Command { get; set; }
private string _lines;
public string Lines
{
get { return this._lines; }
set
{
this._lines = value;
this.OnPropertyChanged("Lines");
}
}
private readonly ObservableCollection<ButtonDataModel> _MyDatabutton = new ObservableCollection<ButtonDataModel>();
public ObservableCollection<ButtonDataModel> MyData { get { return _MyDatabutton; } }
private readonly ObservableCollection<textboxModel> _MyDatatxtbox = new ObservableCollection<textboxModel>();
public ObservableCollection<textboxModel> MyDatatxtbox { get { return _MyDatatxtbox; } }
private readonly ObservableCollection<LabelDataModel> _MyDataLabel = new ObservableCollection<LabelDataModel>();
public ObservableCollection<LabelDataModel> MyDataLabel { get { return _MyDataLabel; } }
public void addcommand()
{
int num= 1;
for (int i = 0; i < num; i++)
{
MyDatatxtbox.Add(new textboxModel
{
isactive = "1",
});
MyData.Add(new ButtonDataModel
{
Command = new Relaycommand(o => search()),
Content = "Add info",
isactive = "1",
});
}
}
public void search( )
{
var asss = MyDatatxtbox.Where(a=> a.isactive == "1").Select(a => a.Text);
var itemstoremove = MyDatatxtbox.Where(i => i.isactive == "1").ToList();
foreach (var s in asss)
{
foreach (var a in itemstoremove)
{
if (a.isactive == "1")
{
MessageBox.Show(s);
buttreadonly = true;
}
}
}
// var itemstoremove = MyDatatxtbox.Where(i => i.isactive == "1").ToList();
foreach(var a in itemstoremove)
{
a.isactive = "0";
}
//foreach (var a in itemstoremove)
//{
// a.txtboxreadonly = true;
//}
// var itemstoremovebutton = MyData.Where(i => i.isactive == "1").ToList();
// foreach (var a in itemstoremovebutton)
// {
//// MyData.Remove(a);
// a.isactive = "0";
// }
}
}
window.xaml:
<GroupBox Header="Audit Information" Grid.Row="1">
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="0" Text="Member ID"></TextBlock>
<TextBox HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="1" Width="85" ></TextBox>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="2" Text="Claim Number"></TextBlock>
<TextBox HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="3" Width="85" ></TextBox>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="4" Text="Date Audited"></TextBlock>
<TextBox HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="5" Width="85" ></TextBox>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="6" Text="Query ID"></TextBlock>
<TextBox HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="7" Width="85" ></TextBox>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="8" Text="Audit ID"></TextBlock>
<TextBox HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="9" Width="85" ></TextBox>
<Button HorizontalAlignment="Center" VerticalAlignment="Center" Width="85" Height="25" Command="{Binding AddCommand}" Content="Add" Grid.Column="10"></Button>
</Grid>
</GroupBox>
<GroupBox Grid.Row="2" Margin="0,0,0,0" Header="Line Information" >
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="3.2*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="1.8*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Height="22" Grid.Column="0">
<Label HorizontalAlignment="Center" Content="DOS" />
</StackPanel>
<ItemsControl Grid.Column="0" Grid.Row="1" ItemsSource="{Binding adt.MyDatatxtbox}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,50">
<TextBox IsReadOnly="{Binding txtboxreadonly}" Text="{Binding Text, Mode=TwoWay}" Height="25" Width="85" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<StackPanel Height="22" Grid.Column="1">
<Label HorizontalAlignment="Center" Content="CPT" />
</StackPanel>
<ItemsControl Grid.Column="1" Grid.Row="1" ItemsSource="{Binding adt.MyDatatxtbox}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,50">
<TextBox IsReadOnly="{Binding txtboxreadonly}" Margin="0,0,30,0" Text="{Binding Text, Mode=TwoWay}" Height="25" Width="85" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<StackPanel Height="22" Grid.Column="2">
<Label HorizontalAlignment="Right" Content="Open-close Modifier" Margin="0,0,-17,0" Width="121" />
</StackPanel>
<ItemsControl Grid.Column="2" Grid.Row="1" ItemsSource="{Binding adt.MyDatatxtbox}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,50">
<TextBox IsReadOnly="{Binding txtboxreadonly}" Margin="0,0,30,0" Text="{Binding Text, Mode=TwoWay}" Height="25" Width="85" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<StackPanel Height="22" Grid.Column="3">
<Label HorizontalAlignment="Center" Content="Comments" />
</StackPanel>
<ItemsControl Grid.Column="3" Grid.Row="1" ItemsSource="{Binding adt.MyDatatxtbox}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,10">
<RichTextBox IsReadOnly="{Binding txtboxreadonly}" Margin="0,0,0,0" Height="65" Width="425" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<StackPanel Height="22" Grid.Column="4">
<Label HorizontalAlignment="Center" Content="Line Status" />
</StackPanel>
<ItemsControl Grid.Column="4" Grid.Row="1" ItemsSource="{Binding adt.MyDatatxtbox}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="10,0,0,50">
<ComboBox IsEnabled= "{Binding txtboxreadonly}" Margin="0,0,0,0" Height="25" Width="95" >
<ComboBoxItem Content="Coffie"></ComboBoxItem>
<ComboBoxItem Content="Tea"></ComboBoxItem>
</ComboBox>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<StackPanel Height="22" Grid.Column="5">
<Label HorizontalAlignment="Center" Content="Additional Comments" />
</StackPanel>
<ItemsControl Grid.Column="5" Grid.Row="1" ItemsSource="{Binding adt.MyDatatxtbox}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,10">
<RichTextBox IsReadOnly="{Binding txtboxreadonly}" Margin="0,0,0,0" Height="65" Width="425" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<ItemsControl Grid.Column="6" Grid.Row="1" ItemsSource="{Binding adt.MyData}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,50">
<Button Margin="0,0,0,0" Height="25" Width="55" Content="{Binding Content}" Command="{Binding Command}" >
</Button>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</ScrollViewer>
</GroupBox>
</Grid>
</Grid>
</TabItem>
</TabControl>
So the question is how to disable/readonly the Line Information ,textbox and cpt on add info button click.
Dirty way would be adding a "global" bool property in your ViewModel and binding it to your Controls IsEnabled/ReadOnly Properties.
Is there any way to get the index of the data which is binded to the ItemsControl, when a button is clicked?
<ItemsControl x:Name="ic_schranke" DataContext="{Binding Schranke}" >
<ItemsControl.ItemTemplate>
<DataTemplate >
<Button Height="80" x:Name="btn_open" Click="btn_open_Click" HorizontalAlignment="Stretch" Style="{StaticResource TransparentStyle}">
<Grid HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="30*"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<Rectangle x:Name="rect" Grid.ColumnSpan="3" Grid.Row="1" Opacity="0.65" Grid.Column="0" Fill="#FFCEEAFF"/>
<Border CornerRadius="25" Height="50" Width="50" HorizontalAlignment="Center" Grid.Column="0" Grid.Row="1">
<Border.Background>
<ImageBrush ImageSource="/Assets/schranken.jpg" />
</Border.Background>
</Border>
<TextBlock Name="schranken_name" Grid.Column="1" Grid.Row="1" Text="{Binding name}" VerticalAlignment="Center" HorizontalAlignment="Center" FontWeight="ExtraLight" Foreground="Black" />
</Grid>
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Here is the sample data which is binded to the IC:
List<Schranke> elements;
public UserPage()
{
this.InitializeComponent();
elements = new List<Schranke>();
for (var i = 1; i < 15; i++)
elements.Add(new Schranke() { name = $"Schranke NR:{i}" });
this.ic_schranke.ItemsSource = elements;
}
And here is the code in the button click event:
private async void btn_open_Click(object sender, RoutedEventArgs e)
{
Grid grid = (sender as Button).Content as Grid;
//Debug.WriteLine($"content {tb.Text} clicked");
var tmp_background = grid.Background;
grid.Background = new SolidColorBrush(new Windows.UI.Color() { A = 255, R = 78, G = 170, B = 44 });
VibrationDevice testVibrationDevice = VibrationDevice.GetDefault();
testVibrationDevice.Vibrate(System.TimeSpan.FromMilliseconds(150));
await Task.Delay(3000);
grid.Background = tmp_background;
}
Maybe something along the lines of this:
the presenter - put this in the data context
public class SchrankePresenter : INotifyPropertyChanged
{
private List<Schranke> _elements;
public List<Schranke> Elements
{
get { return _elements; }
set
{
_elements = value;
OnPropertyChanged("Elements");
}
}
public ICommand ClickCommand { get; set; }
private void OnPropertyChanged(string propName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
}
public event PropertyChangedEventHandler PropertyChanged;
public SchrankePresenter()
{
var elements = new List<Schranke>();
for (var i = 1; i < 15; i++)
elements.Add(new Schranke() { Name = $"Schranke NR:{i}" });
Elements = elements;
ClickCommand = new DelegateCommand(ClickAction);
}
public void ClickAction(Schranke item)
{
VibrationDevice.GetDefault().Vibrate(TimeSpan.FromMilliseconds(150));
}
}
public class Schranke
{
public string Name { get; set; }
}
the template:
<ListView ItemsSource="{Binding Elements}">
<ListView.ItemTemplate>
<DataTemplate>
<Button Height="80"
HorizontalAlignment="Stretch"
Command="{Binding ClickCommand}"
Style="{StaticResource TransparentStyle}">
<Grid HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="1*" />
<RowDefinition Height="30*" />
<RowDefinition Height="1*" />
</Grid.RowDefinitions>
<Rectangle x:Name="rect"
Grid.Row="1"
Grid.Column="0"
Grid.ColumnSpan="3"
Fill="#FFCEEAFF"
Opacity="0.65" />
<Border Grid.Row="1"
Grid.Column="0"
Width="50"
Height="50"
HorizontalAlignment="Center"
CornerRadius="25">
<Border.Background>
<ImageBrush ImageSource="/Assets/schranken.jpg" />
</Border.Background>
</Border>
<TextBlock Name="schranken_name"
Grid.Row="1"
Grid.Column="1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontWeight="ExtraLight"
Foreground="Black"
Text="{Binding Name}" />
</Grid>
</Button>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
you can do the background animation using a storyboard/visualstate
EDIT : regarding the DelegateCommand, it's a simple implementation I use for my WPF apps -
internal class DelegateCommand<T> : ICommand
{
private Action<T> _clickAction;
public DelegateCommand(Action<T> clickAction)
{
_clickAction = clickAction;
}
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
_clickAction((T)parameter);
}
}
I'm working on my first UWP app and I want create a UI like this . For each list item (project) there'll be a set of buttons. For certain list items(projects) some of these buttons will be disabled some times. So I need to disable and change the image for such button in those list items(projects).
I tried to implement it using a list view like this. But I am not sure how I can enable/disable some of those buttons depending on the condition.
Tried adding a DataContextChanged event and trying to access the buttons there. But not sure how I can access those buttons.
Please let me know whether the following approach is correct or is there a better way to do what I am trying to achieve in the above image.
<ListView x:Name="stepsListView" Margin="10,0,0,0" RequestedTheme="Dark" FontSize="24" Background="{StaticResource procedure_app_white}" Foreground="Black" BorderThickness="1.5" BorderBrush="Transparent" ItemsSource="{Binding projectList}" HorizontalAlignment="Left">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</ListView.ItemContainerStyle>
<!-- Item -->
<ListView.ItemTemplate>
<DataTemplate>
<Border BorderThickness="0,0,0,1" BorderBrush="#c0c0c0">
<Grid Width="auto" HorizontalAlignment="Stretch" DataContextChanged="Grid_DataContextChanged" >
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
</Grid.ColumnDefinitions>
<TextBlock VerticalAlignment="Center" FontSize="30" Grid.Row="0" Grid.ColumnSpan="7" Text="{Binding projectName}" Foreground="{StaticResource procedure_app_orange_text }" />
<Button x:Name="warningButton" Width="40" Height="40" Grid.Column="1" Grid.Row="1" Tag="{Binding projectId}" Click="warningButtonClick" Foreground="{StaticResource procedure_app_orange_text }">
<Button.Background>
<ImageBrush ImageSource="Asset/step_ncwr.png">
</ImageBrush>
</Button.Background>
</Button>
<Button x:Name="commentButton" Width="40" Height="40" Grid.Column="2" Grid.Row="1" Tag="{Binding projectId}" Click="CommentButtonClick" Foreground="{StaticResource procedure_app_orange_text }" IsTapEnabled="True">
<Button.Background>
<ImageBrush ImageSource="Asset/step_comment.png">
</ImageBrush>
</Button.Background>
</Button>
<Button x:Name="imageButton" Width="40" Height="40" Grid.Column="3" Grid.Row="1" Tag="{Binding projectId}" Click="ImageButtonClick" Foreground="{StaticResource procedure_app_orange_text }">
<Button.Background>
<ImageBrush ImageSource="Asset/step_image.png">
</ImageBrush>
</Button.Background>
</Button>
</Grid>
</Border>
</DataTemplate>
</ListView.ItemTemplate>
The answer is to variable dependent on what structure you've gone with so I am going to make some assumptions and roll with it.
First I am going to assume your ViewModel has an ObservableCollection called ProjectList and that this ProjectList is made up of ProjectModel's
ProjectModel.cs
public class ProjectModel : INotifyPropertyChanged{
private bool _isNcwrEnabled;
public bool IsNcwrEnabled{
get{ return _isNcwrEnabled; }
set{ _isNcwrEnabled = value; OnPropertyChanged("IsNcwrEnabled"); }
}
private bool _isCommentEnabled;
public bool IsCommentEnabled{
get{ return _isCommentEnabled; }
set{ _isCommentEnabled= value; OnPropertyChanged("IsCommentEnabled"); }
}
private bool _isImageEnabled;
public bool IsImageEnabled{
get{ return _isImageEnabled; }
set{ _isImageEnabled= value; OnPropertyChanged("IsImageEnabled"); }
}
public void OnPropertyChanged(String prop)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(prop));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
In your ViewModel you should have
ObservableCollection<ProjectModel> ProjectList {get; private set; }
Finally in your View
<Button IsEnabled="{Binding IsNcwrEnabled}" x:Name="warningButton" Width="40" Height="40" Grid.Column="1"
Grid.Row="1" Tag="{Binding projectId}" Click="warningButtonClick"
Foreground="{StaticResource procedure_app_orange_text }">
<Button.Background>
<ImageBrush ImageSource="Asset/step_ncwr.png"/>
</Button.Background>
</Button>
<Button IsEnabled="{Binding IsCommentEnabled}" x:Name="commentButton" Width="40" Height="40" Grid.Column="2"
Grid.Row="1" Tag="{Binding projectId}" Click="CommentButtonClick"
Foreground="{StaticResource procedure_app_orange_text }" IsTapEnabled="True">
<Button.Background>
<ImageBrush ImageSource="Asset/step_comment.png"/>
</Button.Background>
</Button>
<Button IsEnabled="{Binding IsImageEnabled}" x:Name="imageButton" Width="40" Height="40" Grid.Column="3"
Grid.Row="1" Tag="{Binding projectId}" Click="ImageButtonClick"
Foreground="{StaticResource procedure_app_orange_text }">
<Button.Background>
<ImageBrush ImageSource="Asset/step_image.png"/>
</Button.Background>
</Button>
Summary of Changes
The models in the collection that your ListView is bound to needs to contain enabled properties for your Buttons to bind to
In your View, bind your Buttons to your new properties