I'm trying to add an additional feature to my custom control spinner but I get an error when I attempt to add another command. Anyone who has experience with this, could you possibly explain why this continues to error out. You can find the line in question by just searching for 'MouseUp' which is near the lower 3rd of the XAML. When i attempt to add it, it crashes.
The error:
Exception thrown: 'System.Windows.Markup.XamlParseException' in
PresentationFramework.dll
Numeric.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:btl="clr-namespace:NumericSpinner"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
mc:Ignorable="d">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/NumericSpinner;component/Resources/AllBrushes.xaml" />
</ResourceDictionary.MergedDictionaries>
<Style TargetType="{x:Type btl:NumericSpinnerControl}">
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type btl:NumericSpinnerControl}">
<Grid Background="{Binding Path=Background, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" >
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
</Grid.RowDefinitions>
<!--
we use the TemplatedParent binding to get a reference to the control
this template has been applied to, so we can access the property on it
-->
<TextBox Grid.Row="0"
Grid.Column="0"
Width="Auto"
Margin="0,0,1,0"
VerticalAlignment="Center"
BorderThickness="0"
BorderBrush="Transparent"
IsReadOnly="{Binding RelativeSource={RelativeSource TemplatedParent},
Path=IsReadOnly,
Mode=TwoWay}"
Text="{Binding RelativeSource={RelativeSource TemplatedParent},
Path=FormattedValue,
Mode=TwoWay,
NotifyOnTargetUpdated=True,
NotifyOnSourceUpdated=True,
UpdateSourceTrigger=LostFocus,
NotifyOnValidationError=True}"
btl:TextBoxBehavior.SelectAllTextOnFocus ="{Binding RelativeSource={RelativeSource TemplatedParent},
Path=SelectAllOnGotFocus,
Mode=TwoWay}"
>
</TextBox>
<Grid x:Name="grid1"
Grid.Column="1"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<RepeatButton Grid.Row="0"
Grid.Column="1"
Width="22"
Height="11"
Background="Transparent"
IsEnabled="{Binding RelativeSource={RelativeSource TemplatedParent},
Path=CanIncrement}"
Command="{x:Static btl:NumericSpinnerControl.IncreaseCommand}"
MouseUp="{x:Static btl:NumericSpinnerControl.MouseUpCommand}">
<RepeatButton.Content>
<Rectangle Width="16"
Height="5"
Fill="{StaticResource BrushScrollUp}" />
</RepeatButton.Content>
<RepeatButton.InputBindings>
<MouseBinding MouseAction="RightClick" Command="{x:Static btl:NumericSpinnerControl.SetValueToMaximumCommand}"/>
</RepeatButton.InputBindings>
</RepeatButton>
<RepeatButton Grid.Row="1"
Grid.Column="1"
Width="22"
Height="11"
Background="Transparent"
IsEnabled="{Binding RelativeSource={RelativeSource TemplatedParent},
Path=CanDecrement}"
Command="{x:Static btl:NumericSpinnerControl.DecreaseCommand}">
<RepeatButton.Content>
<Rectangle Width="16"
Height="5"
Fill="{StaticResource BrushScrollDown}" />
</RepeatButton.Content>
<RepeatButton.InputBindings>
<MouseBinding MouseAction="RightClick" Command="{x:Static btl:NumericSpinnerControl.SetValueToMinimumCommand}"/>
</RepeatButton.InputBindings>
</RepeatButton>
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Resource dictionary entries should be defined here. -->
</ResourceDictionary>
The commands being called are these:
public static RoutedCommand IncreaseCommand { get; set; }
protected static void OnIncreaseCommand(Object sender, ExecutedRoutedEventArgs e)
{
NumericSpinnerControl control = sender as NumericSpinnerControl;
if (control != null)
{
Console.WriteLine("Pressed");
control.OnIncrease();
}
}
protected void OnIncrease()
{
Value = LimitValueByBounds(Value + Increment, this);
}
public static RoutedCommand MouseUpCommand { get; set; }
protected static void OnMouseUpCommand(Object sender, ExecutedRoutedEventArgs e)
{
NumericSpinnerControl control = sender as NumericSpinnerControl;
if (control != null)
{
Console.WriteLine("mouse up");
}
}
private static void InitializeCommands()
{
// create instances
IncreaseCommand = new RoutedCommand("IncreaseCommand", typeof(NumericSpinnerControl));
MouseUpCommand = new RoutedCommand("MouseUpCommand", typeof(NumericSpinnerControl));
// register the command bindings - if the buttons get clicked, call these methods.
CommandManager.RegisterClassCommandBinding(typeof(NumericSpinnerControl), new CommandBinding(IncreaseCommand, OnIncreaseCommand));
CommandManager.RegisterClassCommandBinding(typeof(NumericSpinnerControl), new CommandBinding(MouseUpCommand, OnMouseUpCommand));
}
Related
I have MainWindowViewModel and AccountViewModel.
When I click 'Login' on my MainView:
data about AvaliableExchages is fetched from database.
Property CurrentViewModel is set to AccountViewModel.
AvaliableExchanges property now has 2 strings ("Binance" and "Bitrue"). I can see it in debugger.
The problem is that I can't see them in the View. Combobox that binds its ItemsSource property to AvaliableExchanges Property doesn't show items.
MainViewModel:
internal class MainWindowViewModel : BaseViewModel
{
private List<AppUser> _appUsers = new List<AppUser>();
public List<AppUser> AppUsers
{
get => _appUsers;
set => Set(ref _appUsers, value);
}
public BaseViewModel _currentViewModel;
public BaseViewModel CurrentViewModel
{
get => _currentViewModel;
set => Set(ref _currentViewModel, value);
}
public ICommand LoginCommand { get; }
public bool CanLoginCommandExecute(object p) => true;
public void OnLoginCommandExecuted(object p)
{
if (!string.IsNullOrEmpty(Username) && !string.IsNullOrEmpty(Password))
{
AppUsers = AppUser.GetAppUserByLoginAndPawwsord(Username, Password);
if (AppUsers.Count > 0)
{
List<string> avaliableExchanges = new List<string>();
foreach(var user in AppUsers)
{
avaliableExchanges.Add(user.Exchange);
}
CurrentViewModel = new AccountViewModel(avaliableExchanges);
LoginViewVisibility = Visibility.Collapsed;
MainMenuVisibility = Visibility.Visible;
}
}
}
public MainWindowViewModel()
{
LoginCommand = new RelayCommand(OnLoginCommandExecuted, CanLoginCommandExecute);
}
}
AccountViewModel:
internal class AccountViewModel : BaseViewModel
{
private ObservableCollection<string> _avaliableExchanges;
public ObservableCollection<string> AvaliableExchanges
{
get => _avaliableExchanges;
set => Set(ref _avaliableExchanges, value);
}
public AccountViewModel()
{
}
public AccountViewModel(List<string> avaliableExchanges)
{
AvaliableExchanges = new ObservableCollection<string>(avaliableExchanges);
}
}
MainWindow:
<Window x:Class="ShababTrade.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ShababTrade"
xmlns:vm="clr-namespace:ShababTrade.ViewModels"
xmlns:views="clr-namespace:ShababTrade.Views"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
mc:Ignorable="d"
Title="Shabab Trade" Height="450" Width="800"
WindowState="Maximized" Background="#FF111111">
<Window.DataContext>
<vm:MainWindowViewModel/>
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border Grid.Row="0" Grid.Column="0" BorderThickness="0.5" BorderBrush="DarkGray" Margin="5" CornerRadius="5" Visibility="{Binding MainMenuVisibility}">
<StackPanel Orientation="Horizontal" Margin="5">
<Button Style="{StaticResource MainTabStyle}" Background="{Binding AccountTabBackground}" Command="{Binding SelectMainMenuTabCommand}" CommandParameter="Account" Content="Account" />
<Button Style="{StaticResource MainTabStyle}" Background="{Binding TradeHistoryTabBackground}" Command="{Binding SelectMainMenuTabCommand}" CommandParameter="History" Content="Trade History" />
<Button Style="{StaticResource MainTabStyle}" Background="{Binding SpotTabBackground}" Command="{Binding SelectMainMenuTabCommand}" CommandParameter="Spot" Content="Spot" />
<Button Style="{StaticResource MainTabStyle}" Background="{Binding AutoTradingTabBackground}" Command="{Binding SelectMainMenuTabCommand}" CommandParameter="Auto" Content="Auto Trading" Cursor="Hand" />
<Button Style="{StaticResource MainTabStyle}" Background="{Binding FuturesTabBackground}" Command="{Binding SelectMainMenuTabCommand}" CommandParameter="Futures" Content="Futures" Cursor="Hand" />
</StackPanel>
</Border>
<Border Grid.Row="1" Grid.Column="0" BorderThickness="3" CornerRadius="5" Width="350" Height="430"
BorderBrush="{StaticResource PrimaryColorBrush}"
Background="{StaticResource WhiteColorBrush}" Visibility="{Binding LoginViewVisibility}">
<StackPanel>
<TextBlock Margin="0 30 0 0" FontSize="36" TextAlignment="Center" Text="Login"/>
<TextBox Margin="10 50 10 0" FontSize="20" materialDesign:HintAssist.Hint="Username"
Text="{Binding Username}" Cursor="Arrow"/>
<TextBox Margin="10 40 10 0" FontSize="20" materialDesign:HintAssist.Hint="Password"
Text="{Binding Password}" Cursor="Arrow"/>
<Button Margin="10 50 10 0" FontSize="20" Content="Login" Height="40"
Background="{StaticResource SecondaryColorBrush}"
Style="{StaticResource LoginButtonStyle}"
Command="{Binding LoginCommand}" Cursor="Hand"/>
<TextBlock Margin="0 20 0 0" FontSize="16" TextAlignment="Center" >
<Run Text="Not a member?"/>
<Hyperlink Foreground="{StaticResource HyperlinkColorBrush}">Sign in</Hyperlink>
</TextBlock>
</StackPanel>
</Border>
<ContentControl Grid.Row="1" Grid.Column="0" Content="{Binding CurrentViewModel}" Visibility="{Binding MainMenuVisibility}">
</ContentControl>
</Grid>
</Window>
AccountView:
<UserControl x:Class="ShababTrade.Views.AccountView"
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:ShababTrade.Views"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:views="clr-namespace:ShababTrade.ViewModels"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.DataContext>
<views:AccountViewModel/>
</UserControl.DataContext>
<UserControl.Resources>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="White"/>
</Style>
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Border Grid.Row="0" Grid.Column="0" BorderThickness="0.5" BorderBrush="DarkGray" Margin="5" CornerRadius="5">
<StackPanel>
<StackPanel Orientation="Horizontal" Margin="1 10 0 0">
<TextBlock Text="Exchange:" Foreground="#D81D3C" FontSize="16" Margin="8 0 0 0"/>
<ComboBox Width="100" Height="25" Margin="5 0 0 0" HorizontalContentAlignment="Left" Padding="5 2 5 0"
Background="#2D2D2D" Foreground="White" materialDesign:ColorZoneAssist.Mode="PrimaryDark"
ItemsSource="{Binding AvaliableExchanges, Mode=TwoWay}">
</ComboBox>
</StackPanel>
<ListView Grid.Row="1" Grid.Column="0" ItemsSource="{Binding Balances}" Foreground="White" >
<ListView.Resources>
<Style TargetType="{x:Type GridViewColumnHeader}" BasedOn="{StaticResource MaterialDesignFlatButton}">
<Setter Property="HorizontalContentAlignment" Value="Left" />
</Style>
</ListView.Resources>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem" BasedOn="{StaticResource MaterialDesignGridViewItem}">
<Setter Property="Focusable" Value="false"/>
</Style>
</ListView.ItemContainerStyle>
<ListView.View>
<GridView>
<GridView.ColumnHeaderContainerStyle>
<Style BasedOn="{StaticResource {x:Type GridViewColumnHeader}}" TargetType="{x:Type GridViewColumnHeader}">
<Setter Property="IsHitTestVisible" Value="False"/>
</Style>
</GridView.ColumnHeaderContainerStyle>
<GridView.ColumnHeaderTemplate>
<DataTemplate>
<TextBlock Foreground="White" Text="{Binding}"/>
</DataTemplate>
</GridView.ColumnHeaderTemplate>
<GridViewColumn Header="Asset" DisplayMemberBinding="{Binding Asset}" Width="100"/>
<GridViewColumn Header="Free" DisplayMemberBinding="{Binding Free, StringFormat=N2}" Width="100"/>
<GridViewColumn Header="Locked" DisplayMemberBinding="{Binding Locked, StringFormat=N2}" Width="100"/>
<GridViewColumn Header="Total" DisplayMemberBinding="{Binding Total, StringFormat=N2}" Width="100"/>
<GridViewColumn Header="RubValue" DisplayMemberBinding="{Binding RubValue, StringFormat=N2}" Width="100"/>
</GridView>
</ListView.View>
</ListView>
</StackPanel>
</Border>
</Grid>
</UserControl>
A UserControl must not explicitly set its own DataContext.
Remove
<UserControl.DataContext>
<views:AccountViewModel/>
</UserControl.DataContext>
from the AccountView XAML, because it sets a different AccountViewModel instance than the one the control is expected to operate with.
Also note that it is poinless to set Mode=TwoWay on an ItemsSource Binding.
I am trying to learn how to use the IValueConverter to enable/disable controls (in this case a button) using the boolean-property of an item selected in a listbox. The button in question is the "TestButton". I believe I have the XAML for it setup correctly but it does not enable when I add and select a user defined item or disable when I select one of the other items in the listbox. The listbox contains a list of "Drink" objects that can be added to. When one is added it becomes a user defined item. Now I believe I am missing something but I am not sure what. Any help will be appreciated.
ViewModel code here:
<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<local:Drinks x:Key="Drink"/>
<local:EnableConverter x:Key="EnableConverter"/>
<BooleanToVisibilityConverter x:Key="BoolToVis"/>
<ControlTemplate x:Key="validationTemplate">
<DockPanel>
<TextBlock Foreground="Red" FontSize="20">!</TextBlock>
<AdornedElementPlaceholder/>
</DockPanel>
</ControlTemplate>
<Style x:Key="textStyleTextBox" TargetType="TextBox">
<Setter Property="Foreground" Value="#333333" />
<Setter Property="MaxLength" Value="40" />
<Setter Property="Width" Value="392" />
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ListBox x:Name="DrinksListBox" HorizontalAlignment="Center" Height="325" Width="275" Margin="0,0,0,0" VerticalAlignment="Center" Grid.Column="0" ItemsSource="{Binding SomeDrinks}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="0,2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Type}" Width="80" Margin="0,0,10,0" Grid.Column="0"/>
<TextBlock Text="{Binding Name}" Width="80" Margin="0,0,10,0" Grid.Column="1" HorizontalAlignment="Left"/>
<TextBlock Text="{Binding NumberOfCans}" Width="80" Margin="0,0,10,0" Grid.Column="2" HorizontalAlignment="Left"/>
<Button x:Name="DrinkDeleteButton" Content="Delete" Visibility="{Binding Path=IsUserDefined, Converter={StaticResource BoolToVis}}" Click="CmdDeleteDrink_Clicked" HorizontalAlignment="Left" Grid.Column="3"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<TextBox x:Name="DrinkNameTextBox" Grid.Column="1" HorizontalAlignment="Left" Height="45" Margin="0,0,0,100" TextWrapping="Wrap" Text="Enter Drink Name" VerticalAlignment="Center" Width="240" FontSize="20" VerticalContentAlignment="Center"/>
<TextBox x:Name="NumberCansTextBox" Style="{StaticResource textStyleTextBox}" Grid.Column="1" HorizontalAlignment="Left" Height="45" Margin="0,0,0,150" VerticalAlignment="Bottom" Width="240" FontSize="20" VerticalContentAlignment="Center">
<TextBox.Text>
<Binding Path="NumberOfCans" UpdateSourceTrigger="PropertyChanged" Source="{StaticResource Drink}">
<Binding.ValidationRules>
<local:NumberCansValidationRule Min="0" Max="10"/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
<ComboBox x:Name="DrinkTypeComboBox" Grid.Column="1" HorizontalAlignment="Left" Margin="0,47,0,0" VerticalAlignment="Top" Width="240" Height="45" ItemsSource="{Binding Drinks, Mode=OneWay}" DisplayMemberPath="Type" FontSize="20"/>
<Button x:Name="AddDrinkButton" Content="Add Drink" Grid.Column="1" HorizontalAlignment="Right" Margin="0,0,10,100" VerticalAlignment="Center" Width="100" Height="45" Click="CmdAddDrink_Clicked">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="IsEnabled" Value="False"/>
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=(Validation.HasError), ElementName=NumberCansTextBox}" Value="False"/>
</MultiDataTrigger.Conditions>
<Setter Property="IsEnabled" Value="True"/>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
<Button x:Name="TestButton" Content="Test" IsEnabled="{Binding Path=IsUserDefined, UpdateSourceTrigger=PropertyChanged, Source={StaticResource Drink}, Converter={StaticResource EnableConverter}}" Grid.Column="1" HorizontalAlignment="Right" Margin="0,70,10,0" VerticalAlignment="Center" Width="100" Height="45"/>
</Grid>
Here is my converter:
namespace WpfApp1
{
class EnableConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
bool isenable = false;
bool b = (bool)value;
if (b == true)
{
isenable = true;
}
return isenable;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
This class contains the "IsUserDefined" property that I am binding to:
public class Drinks
{
private string type;
private string name;
private int numCans;
public Drinks() { }
public Drinks(string type, string name, int numCans)
{
this.type = type;
this.name = name;
this.numCans = numCans;
}
public bool IsUserDefined { get; set; }
public string Type
{
get { return type; }
set
{
if (type != value)
{
type = value;
}
}
}
public string Name
{
get { return name; }
set
{
if (name != value)
{
name = value;
}
}
}
public int NumberOfCans
{
get { return numCans; }
set
{
if (numCans != value)
{
numCans = value;
}
}
}
}
hi in my form(adminentitylist.xaml) file contains the code is below
<ResourceDictionary xmlns:local="clr-namespace:iWatch.Administration"
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"
mc:Ignorable="d"
xmlns:my="clr-namespace:iWatch.UILibrary;assembly=UILibrary"
xmlns:dxg="http://schemas.devexpress.com/winfx/2008/xaml/grid"
xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core"
xmlns:dxb="http://schemas.devexpress.com/winfx/2008/xaml/bars"
xmlns:cmd="clr-namespace:iWatch.UILibrary;assembly=UILibrary"
x:Class="AdminEntityList">
<ControlTemplate x:Key="AddImgBtnTemplate" TargetType="Button">
<Grid>
<Image Name="Normal" Source="/UILibrary;component/Themes/Default/Images/Add.png" Opacity="1.0" Height="18" Width="18"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="Normal" Property="Opacity" Value="0.5"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="Normal" Property="Opacity" Value="0.2"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<ControlTemplate x:Key="DelImgBtnTemplate" TargetType="Button">
<Grid>
<Image Name="Normal" Source="/UILibrary;component/Themes/Default/Images/Delete.png" Opacity="1.0" Height="18" Width="18"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="Normal" Property="Opacity" Value="0.5"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="Normal" Property="Opacity" Value="0.2"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<Style TargetType="{x:Type local:AdminEntityList}">
<Setter Property="FontFamily" Value="Calibri"/>
<Setter Property="dx:ThemeManager.ThemeName" Value="Office2007Black"/>
<Setter Property="Template" >
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:AdminEntityList}">
<DockPanel>
<DockPanel DockPanel.Dock="Top">
<StackPanel Name="StpFilter" Orientation="Horizontal" HorizontalAlignment="Left" Margin="5">
<ContentControl x:Name="FilterCriteriaArea" ContentTemplate="{TemplateBinding FilterCriteriaArea}"/>
</StackPanel>
<StackPanel Name="StpCountry" Orientation="Horizontal" HorizontalAlignment="Right" Margin="5" >
<Label Content="Select Country" Name="lblCountry" Style="{StaticResource lblNormal}" Margin="10,0,5,7" HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Visibility="Collapsed"/>
<ComboBox Name="cbCountry" Width="170" Style="{StaticResource ddlNormal}" SelectedValue="{Binding CountryKey,Mode=TwoWay}" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="5,2,10,0" Visibility="Collapsed"/>
<Button Content="Filter" Name="btnFilter" Width="70" Height="23" Margin="0,0,10,0" Visibility="Collapsed"/>
</StackPanel>
<StackPanel Name="actinact" Orientation="Horizontal" HorizontalAlignment="Left" Margin="5">
<CheckBox Name="chkactive" Height="18" Content="Active" Checked="chkactive_Checked"></CheckBox>
<CheckBox Name="chkinactive" Height="18" Content="In-Active"/>
</StackPanel>
<StackPanel Name="StpAddDel" Orientation="Horizontal" HorizontalAlignment="Right" Margin="5">
<Button Name="BtnAdd" Height="20" Width="20" Margin="5,0" Template="{StaticResource AddImgBtnTemplate}" />
<Button Name="BtnDel" Height="20" Width="20" Margin="5,0" Template="{StaticResource DelImgBtnTemplate}" />
</StackPanel>
</DockPanel>
<DockPanel Name="AMLDP">
<dxg:GridControl Name="genericGrid" AutoPopulateColumns="true" ShowBorder="False"
DesignTimeDataSourceRowCount="50" DataSource="{Binding}"
Padding="0" Margin="0,0,0,0" IsManipulationEnabled="True" dx:ThemeManager.ThemeName="CPCEGridTheme">
<dxg:GridControl.Resources>
<ResourceDictionary x:Key="CPCEGridTheme" Source="/UILibrary;component/Themes/Default/Styles/DataGrid/CPCEGridTheme.xaml" />
</dxg:GridControl.Resources>
<dxg:GridControl.View>
<dxg:TableView x:Name="tblGeneric" MultiSelectMode="Row" AllowGrouping="True" ClipToBounds="True" AutoWidth="True"
ShowGroupPanel="False" ShowHorizontalLines="True" ShowVerticalLines="False" AllowMoveColumnToDropArea="False" AllowDrop="False"
IsGroupPanelMenuEnabled="False" AllowEditing="False" NavigationStyle="Cell" Margin="0"
GroupRowStyle="{StaticResource OddEvenRowStyle}" VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingStackPanel.VirtualizationMode="Standard" AllowHorizontalScrollingVirtualization="True"
RowStyle="{StaticResource OddEvenRowStyle}" CellStyle="{StaticResource FocusedCellStyle}">
<dxg:TableView.RowCellMenuCustomizations>
<dxb:BarButtonItem Name="ctmView" IsVisible="False" Content="View" Command="{x:Static cmd:CustomCommands.View}" />
<dxb:BarButtonItem Name="ctmEdit" IsVisible="True" Content="Edit" Command="{x:Static cmd:CustomCommands.Edit}" />
<dxb:BarButtonItem Name="ctmMIQ" IsVisible="False" Content="Manage Interview Questions" Command="{x:Static cmd:CustomCommands.ManageInterviewQuestions}" />
<dxb:BarButtonItem Name="ctmActivate" IsVisible="False" Content="Activate" Command="{x:Static cmd:CustomCommands.Activate}" />
<dxb:BarButtonItem Name="ctmCopyInterviewType" IsVisible="False" Content="Copy Interview Type" Command="{x:Static cmd:CustomCommands.CopyInterviewType}" />
<dxb:BarButtonItem Name="ctmAssignInvGroup" IsVisible="False" Content="Assign Investigative Group" Command="{x:Static cmd:CustomCommands.AssignInvestigativeGroup}" />
<dxb:BarButtonItem Name="ctmCopySelected" IsVisible="False" Content="Copy From Selected" Command="{x:Static cmd:CustomCommands.CopyInterviewTemplate}" />
</dxg:TableView.RowCellMenuCustomizations>
</dxg:TableView>
</dxg:GridControl.View>
<dxg:GridControl.CommandBindings>
<CommandBinding x:Name="cmdEdit" Command="{x:Static cmd:CustomCommands.Edit}" />
<CommandBinding x:Name="cmdView" Command="{x:Static cmd:CustomCommands.View}" />
<CommandBinding x:Name="cmdMIQ" Command="{x:Static cmd:CustomCommands.ManageInterviewQuestions}" />
<CommandBinding x:Name="cmdActivate" Command="{x:Static cmd:CustomCommands.Activate}" />
<CommandBinding x:Name="cmdCopyInterviewType" Command="{x:Static cmd:CustomCommands.CopyInterviewType}" />
<CommandBinding x:Name="cmdAssignInvestigativeGroup" Command="{x:Static cmd:CustomCommands.AssignInvestigativeGroup}" />
<CommandBinding x:Name="cmdCopySelected" Command="{x:Static cmd:CustomCommands.CopyInterviewTemplate}" />
</dxg:GridControl.CommandBindings>
</dxg:GridControl>
</DockPanel>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
in the above code i created the checkbox checked event Checked="chkactive_Checked"
private void chkactive_Checked(object sender, RoutedEventArgs e)
{
}
but the event is not firing and i am getting an error is
Error 14 'AdminEntityList' does not contain a definition for
'chkactive_Checked' and no extension method 'chkactive_Checked'
accepting a first argument of type 'AdminEntityList' could be found
(are you missing a using directive or an assembly reference?)
please help me with is problem...
Here is a simple example:
<Window x:Class="CheckboxCheckedCommand.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<CheckBox Content="Case Sensitive" Command="{Binding checkedCommand}"/>
</Grid>
Codebehind:
public partial class MainWindow : Window
{
public ViewModel vm { get; set; }
public MainWindow()
{
InitializeComponent();
vm = new ViewModel();
this.DataContext = vm;
}
}
ViewModel:
public class ViewModel
{
public ICommand checkedCommand { get; set; }
public ViewModel()
{
checkedCommand = new CheckedCommand(this);
}
public void CheckedHandler()
{
//todo - implement your handler
}
}
And of course the Checked Unchecked command:
public class CheckedCommand : ICommand
{
private ViewModel _vm = null;
public CheckedCommand(ViewModel _viewModel)
{
_vm = _viewModel;
}
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
_vm.CheckedHandler();
}
}
Let me know if you need more details, maybe a parameter which has to be sent from the view and received by the handler..
I see this as an easy and normal flow for MVVM. You have some instance/static method issue right there.. try the above approach, in my opinion is cleared and helps you decouple the things.
Oh, i forgot to say, Command="{Binding checkedCommand}" , is both applicable for Checked and Unchecked events.
Update 1
This can be your codebehind:
public partial class MainWindow : Window
{
public bool IsChecked
{
get { return (bool)GetValue(IsCheckedProperty); }
set { SetValue(IsCheckedProperty, value); }
}
// Using a DependencyProperty as the backing store for IsChecked. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsCheckedProperty =
DependencyProperty.Register("IsChecked", typeof(bool), typeof(MainWindow), new PropertyMetadata(false, new PropertyChangedCallback(PropertyChanged)));
private static void PropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
//textbox.ScrollToEnd(); //An object reference is required for the non-static field.
MainWindow localWindow = (MainWindow)obj;
Console.WriteLine(localWindow.TestString);
}
public string TestString { get; set; }
public MainWindow()
{
InitializeComponent();
TestString = "test";
this.DataContext = this;
}
}
And you CheckBox definition is this now:
<CheckBox Content="Case Sensitive" IsChecked="{Binding IsChecked}"/>
You basically define that DependencyProperty with the name IsChecked. Each time you check or uncheck it, the callback method defined there will be called. And may see an example on how to access an instance field from that static method. Good luck!
In order to attempt to get around the problem I outline in Binding Selected RowCount to TextBlock not Firing OnPropertyChanged after DataGrid Scroll; namely updating a TextBlock with the currently selected row count of a DataGrid when it scrolls. I have attempted to introduce the AttachedCommandBehaviour designed by Marlon Grech [an amazing class structure that allows you to bind commands to specific events of a given control].
Now for the question, using this AttachedCommandBehaviour, how can I get a TextBlock to update based upon a DataGrid's SelectionChangedProperty?
The XMAL is
<Window x:Class="ResourceStudio.Views.AddCultureWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:viewModels="clr-namespace:ResourceStudio.ViewModels"
xmlns:converters="clr-namespace:ResourceStudio.Converters"
xmlns:dataAccess="clr-namespace:ResourceStudio.DataAccess"
xmlns:attachedCommand="clr-namespace:AttachedCommandBehavior;assembly=AttachedCommandBehavior"
Title="Add Culture"
Height="510" Width="400"
WindowStartupLocation="CenterOwner"
VerticalContentAlignment="Stretch"
MinWidth="380" MinHeight="295">
<DockPanel HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="24"/>
</Grid.RowDefinitions>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="15*"/>
<ColumnDefinition Width="377*"/>
<ColumnDefinition Width="15*"/>
</Grid.ColumnDefinitions>
<Grid Grid.Column="1">
<Grid>
<Grid.Resources>
<converters:EnumToBooleanConverter x:Key="enumToBooleanConverter"/>
<Style x:Key="HyperlinkButton" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<ContentPresenter/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<GroupBox Header="Filters" Grid.Row="0" Margin="0,0,0,5">
<StackPanel VerticalAlignment="Top">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" Margin="2,2,2,2">
<RadioButton Content="All Cultures" Margin="10,5,10,5"
HorizontalAlignment="Left"
IsChecked="{Binding SelectedFilterType,
Converter={StaticResource enumToBooleanConverter},
ConverterParameter=AllCultures}"/>
<RadioButton Content="Neutral Cultures" Margin="10,5,10,5"
HorizontalAlignment="Left"
IsChecked="{Binding SelectedFilterType,
Converter={StaticResource enumToBooleanConverter},
ConverterParameter=NeutralCultures}"/>
<RadioButton Content="Specific Cultures" Margin="10,5,10,5"
HorizontalAlignment="Left"
IsChecked="{Binding SelectedFilterType,
Converter={StaticResource enumToBooleanConverter},
ConverterParameter=SpecificCultures}"/>
</StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Content="Language:" Grid.Column="0"/>
<TextBox HorizontalAlignment="Stretch" Grid.Column="1"
Margin="2,0,2,0" Height="22"/>
</Grid>
</StackPanel>
</GroupBox>
<DataGrid x:Name="cultureDataGrid" Grid.Row="1" AlternatingRowBackground="Gainsboro" AlternationCount="2"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
AutoGenerateColumns="False" RowHeaderWidth="0" IsReadOnly="True"
CanUserAddRows="False" CanUserDeleteRows="False" SelectionMode="Extended"
EnableRowVirtualization="True" EnableColumnVirtualization="True"
ItemsSource="{Binding Cultures, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged, IsAsync=True}">
<DataGrid.Columns>
<DataGridTextColumn Header="Code" Binding="{Binding Code}" IsReadOnly="True"/>
<DataGridTextColumn Header="Language" Binding="{Binding Language}" IsReadOnly="True"/>
<DataGridTextColumn Header="LocalName" Binding="{Binding LocalName}" IsReadOnly="True"/>
</DataGrid.Columns>
<DataGrid.CellStyle>
<Style TargetType="DataGridCell" BasedOn="{StaticResource {x:Type DataGridCell}}">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="#FF007ACC"/>
<Setter Property="Foreground" Value="White"/>
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.CellStyle>
<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay, IsAsync=True}" />
</Style>
</DataGrid.RowStyle>
</DataGrid>
<StackPanel Grid.Row="2" HorizontalAlignment="Right">
<Button Name="button1" Style="{StaticResource HyperlinkButton}"
Focusable="False">
<TextBlock>
<Hyperlink Focusable="False">
Select All
</Hyperlink>
</TextBlock>
</Button>
</StackPanel>
<GroupBox Grid.Row="3" Header="Options">
<CheckBox Content="Copy default values" Margin="3,3"/>
</GroupBox>
<StackPanel Grid.Row="4" Orientation="Horizontal"
HorizontalAlignment="Right" Margin="0,2,0,2">
<Button Content="Select" Width="70" Height="25"
Margin="0,5,5,5" HorizontalAlignment="Right"
VerticalContentAlignment="Center" IsDefault="True"/>
<Button Content="Cancel" Width="70" Height="25"
Margin="5,5,0,5" HorizontalAlignment="Right"
VerticalContentAlignment="Center" IsCancel="True"/>
</StackPanel>
</Grid>
</Grid>
</Grid>
<StatusBar Grid.Row="1" Margin="0,0.4,0.4,-0.4">
<StatusBarItem DockPanel.Dock="Left" Background="#FF007ACC" Margin="0,2,0,0">
<TextBlock Text="{Binding TotalSelectedCultures}" Margin="5,0,0,0" Foreground="White"/>
</StatusBarItem>
</StatusBar>
</Grid>
</DockPanel>
</Window>
My ViewModel is
public class CultureDataViewModel : ViewModelBase
{
public FilterType SelectedFilterType { get; private set; }
public ICollectionView CulturesView { get; private set; }
public MultiSelectCollectionView<CultureViewModel> Cultures { get; private set; }
public CultureDataViewModel()
{
SelectedFilterType = FilterType.AllCultures;
LoadCultures();
}
void OnCultureViewModelPropertyChanged(object sender, PropertyChangedEventArgs e)
{
string IsSelected = "IsSelected";
(sender as CultureViewModel).VerifyPropertyName(IsSelected);
if (e.PropertyName == IsSelected)
this.OnPropertyChanged("TotalSelectedCultures");
}
void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null && e.NewItems.Count != 0)
foreach (CultureViewModel cultVm in e.NewItems)
cultVm.PropertyChanged += this.OnCultureViewModelPropertyChanged;
if (e.OldItems != null && e.OldItems.Count != 0)
foreach (CultureViewModel cultVm in e.OldItems)
cultVm.PropertyChanged -= this.OnCultureViewModelPropertyChanged;
}
public void LoadCultures()
{
// Fill the Culutres collection...
}
public string TotalSelectedCultures
{
get
{
int selectedCultures = this.Cultures.SelectedItems.Count;
return String.Format("{0:n0} of {1:n0} cultures selected",
selectedCultures,
Cultures.Count);
}
}
}
The link to a downloadable example of the use of the AttachedCommandBehaviour is Here. Your help is most appreciated...
So, as far as I understand, you want to have TextBlock which says:
"5 of 100 items selected"
I've reconstructed your window, the button below the list shows how many items you have selected.
Is that correct? If that is really all you want to do, you don't need to involve the ViewModel at all:
All I did, was this:
<Button Content="{Binding SelectedItems.Count, ElementName=cultureDataGrid}" />
Does this help in some way already or is there a reason for using the pretty complex method with event to command etc.?
EDIT
Your problem basically melts down to "How can I bind to SelectedItems property of a DataGrid. Here is how I solved it:
Define a behavior with a dependency property for the DataGrid, which relays the SelectedItems of the DataGrid to the DependencyProperty:
public class BindableSelectedItems : Behavior<DataGrid>
{
public static readonly DependencyProperty SelectedItemsProperty =
DependencyProperty.Register("SelectedItems", typeof (IList), typeof (BindableSelectedItems), new PropertyMetadata(default(IList), OnSelectedItemsChanged));
private static void OnSelectedItemsChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
{
var grid = ((BindableSelectedItems) sender).AssociatedObject;
if (grid == null) return;
// Add logic to select items in grid
}
public IList SelectedItems
{
get { return (IList) GetValue(SelectedItemsProperty); }
set { SetValue(SelectedItemsProperty, value); }
}
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.SelectionChanged += AssociatedObject_SelectionChanged;
}
void AssociatedObject_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var grid = (DataGrid) sender;
SelectedItems = grid.SelectedItems;
}
}
Attach this behavior to the DataGrid and bind the SelectedItems property to a property on your ViewModel:
<DataGrid x:Name="cultureDataGrid" ItemsSource="{Binding Cultures}">
<i:Interaction.Behaviors>
<behaviors:BindableSelectedItems x:Name="CulturesSelection"
SelectedItems="{Binding SelectedCultures, Mode=OneWayToSource}"/>
</i:Interaction.Behaviors>
with the property on your ViewModel like this:
public IList SelectedCultures
{
get { return _selectedCultures; }
set
{
_selectedCultures = value;
OnPropertyChanged("SelectedCultures");
}
}
If you only want to get the count of selected items, you can bind to the behavior directly and don't need a field on the ViewModel for this:
<TextBlock Text="{Binding Path=SelectedItems.Count, ElementName=CulturesSelection}" Margin="5,0,0,0" Foreground="White"/>
In your ViewModel you can use the SelectedItems property to work with the selection:
var selectedCultures= SelectedCultures.OfType<CultureViewModel>();
I've uploaded the solution, see the link in the comments.
I hope this helps and whish you good luck! There always are a thousand ways to do stuff in WPF and it is really hard to find the best one sometimes...
In WPF, I am creating a simple custom control for my TODO program. It should do the following:
Show up as a ListBox with an Add and Remove button above it.
The Add and Remove buttons should add and remove items from my base class.
I have this working
On pressing F2, I want the list box items to change into a TextBox control.
My main issues/Questions are:
On OnKeyDown, I get the error: This operation is valid only on elements that have this template applied. How do I get around this? This is where I want to press F2, and to be able to make the TextBox visible and Label invisible.
Is there a better way to do this? If my control is a container for buttons AND a text box, should I not be inheriting from ListBox? Should I inherit from Control instead and make it a container?
If so, how do I implement it? Do I basically use the following code in the style, and remove the overrides like OnKeyDown and instead register the KeyDown event for the Textbox? I'll give that a try after this post but let me know if you have any advice.
I had something close working before, in the following code, but now I want this moved from my main Window XAML to the custom control code, and I want to be able to edit on button press:
<!-- In my MainWindow.XAML -->
<TaskDashControls:ListBoxWithAddRemove x:Name="listBoxItems" Grid.Row="1" Grid.Column="3" Grid.RowSpan="3"
ItemsSource="{Binding}">
<TaskDashControls:ListBoxWithAddRemove.ItemTemplate>
<DataTemplate>
<DockPanel>
<Button DockPanel.Dock="Left" Click="SelectItemClick">SELECT</Button>
<TextBlock x:Name="LabelDescription" Visibility="Visible" DockPanel.Dock="Left" Text="{Binding Description}" Height="25" Width="150" />
<TextBox x:Name="EditableDescription" Visibility="Collapsed" DockPanel.Dock="Left" Text="{Binding Description}" Height="25" Width="150" />
<Button DockPanel.Dock="Left" Click="EditTaskItemClick">EDIT</Button>
</DockPanel>
</DataTemplate>
</TaskDashControls:ListBoxWithAddRemove.ItemTemplate>
</TaskDashControls:ListBoxWithAddRemove>
I have now removed the DataTemplate, to move it over to the custom control:
<!-- In my MainWindow.XAML -->
<TaskDashControls:ListBoxWithAddRemove x:Name="listBoxItems" Grid.Row="1" Grid.Column="3" Grid.RowSpan="3"
ItemsSource="{Binding}"/>
Here is the custom control in Generic.XAML:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TaskDash.Controls">
<SolidColorBrush x:Key="WindowBackgroundBrush" Color="#FFF" />
<SolidColorBrush x:Key="SolidBorderBrush" Color="#888" />
<SolidColorBrush x:Key="DisabledForegroundBrush" Color="#888" />
<SolidColorBrush x:Key="DisabledBackgroundBrush" Color="#EEE" />
<SolidColorBrush x:Key="DisabledBorderBrush" Color="#AAA" />
<Style TargetType="{x:Type TextBox}">
<Setter Property="Margin" Value="2" />
</Style>
<Style x:Key="{x:Type local:ListBoxWithAddRemove}" TargetType="{x:Type local:ListBoxWithAddRemove}">
<Setter Property="Margin" Value="3" />
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="KeyboardNavigation.TabNavigation" Value="None"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="MinWidth" Value="120"/>
<Setter Property="MinHeight" Value="20"/>
<Setter Property="AllowDrop" Value="true"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="25" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<!--<Button Grid.Column="0" Grid.Row="0" x:Name="DeleteButton"
Click="DeleteControlClick">Delete</Button>
<Button Grid.Column="1" Grid.Row="0" x:Name="AddButton"
Click="AddControlClick">Add</Button>-->
<Button Grid.Column="0" Grid.Row="0" x:Name="DeleteButton">Delete</Button>
<Button Grid.Column="1" Grid.Row="0" x:Name="AddButton">Add</Button>
<Border
Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="2"
Name="Border"
Background="{StaticResource WindowBackgroundBrush}"
BorderBrush="{StaticResource SolidBorderBrush}"
BorderThickness="1"
CornerRadius="2">
<ScrollViewer
Margin="0"
Focusable="false">
<StackPanel Margin="0" IsItemsHost="True" />
</ScrollViewer>
<!--<ListBox ItemTemplate="{TemplateBinding ItemTemplate}">
<DataTemplate>
<DockPanel>
<TextBlock x:Name="LabelDescription" Visibility="Visible" DockPanel.Dock="Left" Text="{Binding Description}" Height="25" Width="150" />
<TextBox x:Name="EditableDescription" DockPanel.Dock="Left" Text="{Binding Description}" Height="25" Width="150" />
</DockPanel>
</DataTemplate>
</ListBox>-->
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Here is my custom control class
using System;
using System.Windows;
using System.Windows.Controls;
namespace TaskDash.Controls
{
[TemplatePart(Name = "Text", Type = typeof(TextBox))]
[TemplatePart(Name = "LabelText", Type = typeof(TextBlock))]
public class TextBoxWithDescription : Control
{
static TextBoxWithDescription()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(TextBoxWithDescription), new FrameworkPropertyMetadata(typeof(TextBoxWithDescription)));
}
public TextBoxWithDescription()
{
LabelText = String.Empty;
Text = String.Empty;
}
public static readonly DependencyProperty LabelTextProperty =
DependencyProperty.Register("LabelText", typeof(string), typeof(TextBoxWithDescription),
new PropertyMetadata(string.Empty, OnLabelTextPropertyChanged));
private static void OnLabelTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
}
public string LabelText
{
get { return GetValue(LabelTextProperty).ToString(); ; }
set { SetValue(LabelTextProperty, value); }
}
// http://xamlcoder.com/cs/blogs/joe/archive/2007/12/13/building-custom-template-able-wpf-controls.aspx
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(string), typeof(TextBoxWithDescription),
new UIPropertyMetadata(null,
new PropertyChangedCallback(OnTextChanged)
));
private static void OnTextChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
TextBoxWithDescription textBox = o as TextBoxWithDescription;
if (textBox != null)
textBox.OnTextChanged((String)e.OldValue, (String)e.NewValue);
}
protected virtual void OnTextChanged(String oldValue, String newValue)
{
// fire text changed event
this.Text = newValue;
this.RaiseEvent(new RoutedEventArgs(TextChangedEvent, this));
}
public string Text
{
get { return GetValue(TextProperty).ToString(); }
set { SetValue(TextProperty, value); }
}
public static readonly RoutedEvent TextChangedEvent =
EventManager.RegisterRoutedEvent("TextChanged",
RoutingStrategy.Bubble,
typeof(RoutedEventHandler),
typeof(TextBoxWithDescription));
public event RoutedEventHandler TextChanged
{
add { AddHandler(TextChangedEvent, value); }
remove { RemoveHandler(TextChangedEvent, value); }
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
//var textBlock = (TextBlock)this.Template.FindName("LabelText", this);
//if (textBlock != null) textBlock.Text = this.LabelText;
//var textBox = (TextBox)this.Template.FindName("Text", this);
//if (textBox != null) textBox.Text = this.Text;
}
}
}
I would create a class for TODO with Properties: String Desc, Visibility txtBox, Visibility txtBlock. Then items source for the TaskDashControls is List TODO. In xaml you can bind the visibilty property. In the TODO class you can control that when one is visible the other is not.