dipique
Member
- Joined
- Oct 22, 2014
- Messages
- 7
- Programming Experience
- 1-3
I am new to WPF and am having difficulty accomplishing something that is probably pretty simple.
What my app does (or is supposed to do)
Starting with a string of special characters for a language (Spanish in this case: "?????????"), my app is to display a button for each character so the user can press the button and have the character inserted in whatever app they are in. Sort of like a universal character insert toolbar.
My progress so far
I have buttons that display in a grid, and when you click a given button, a message box appears with the character associated with that button (example, "?"). The buttons are created dynamically from the data model.
My problem
I can't figure out how to set the button caption/content to the same character it displays when clicked. My current XAML for the button looks like this:
The data inside the model is as follows:
The output is that each button has the caption of "(Collection)" instead of the appropriate string value.
Bonus Problem
All the buttons are currently laid out vertically, but I'd actually like to set a maximum number of buttons horizontally and have them laid out in a 2d grid. Any pointers on that would be awesome.
The Full Code
MainWindow.xaml.cs:
MainWindow.xaml:
And the Data Model and helper classes, CharacterDataModel.cs:
Thank you!
What my app does (or is supposed to do)
Starting with a string of special characters for a language (Spanish in this case: "?????????"), my app is to display a button for each character so the user can press the button and have the character inserted in whatever app they are in. Sort of like a universal character insert toolbar.
My progress so far
I have buttons that display in a grid, and when you click a given button, a message box appears with the character associated with that button (example, "?"). The buttons are created dynamically from the data model.
My problem
I can't figure out how to set the button caption/content to the same character it displays when clicked. My current XAML for the button looks like this:
C#:
<Button Content="{Binding DataContext.Data, RelativeSource={RelativeSource AncestorType=ItemsControl}}" Command="{Binding DataContext.InsertChar, RelativeSource={RelativeSource AncestorType=ItemsControl}}"
CommandParameter="{Binding}"/>
The data inside the model is as follows:
C#:
Data = new ObservableCollection<string>(Characters);
The output is that each button has the caption of "(Collection)" instead of the appropriate string value.
Bonus Problem
All the buttons are currently laid out vertically, but I'd actually like to set a maximum number of buttons horizontally and have them laid out in a 2d grid. Any pointers on that would be awesome.
The Full Code
MainWindow.xaml.cs:
C#:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new CharacterDataModel();
}
}
C#:
Window x:Class="Special_Character_Inserter.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Special Character Inserter" Height="300" Width="300">
<DockPanel>
<ItemsControl ItemsSource="{Binding Data}" Height="248" VerticalAlignment="Bottom">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Black" Background="Gainsboro" BorderThickness="1" Margin="2">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Button Content="{Binding DataContext.Data, RelativeSource={RelativeSource AncestorType=ItemsControl}}"
Command="{Binding DataContext.InsertChar, RelativeSource={RelativeSource AncestorType=ItemsControl}}"
CommandParameter="{Binding}"/>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.Template>
<ControlTemplate TargetType="ItemsControl">
<ScrollViewer CanContentScroll="True">
<Grid Height="248" Width="275">
<ItemsPresenter Grid.RowSpan="5" Grid.Row="5" Grid.ColumnSpan="5" Grid.Column="5"/>
</Grid>
</ScrollViewer>
</ControlTemplate>
</ItemsControl.Template>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</DockPanel>
</Window>
C#:
class CharacterDataModel
{
const string csCharacters = "?????????";
/// <summary>
/// Fill character array with upper and lower versions of each character
/// </summary>
private string[] GetSpecialCharsFromString(string chars)
{
string[] RetVal = new string[chars.Length * 2];
for (int i = 0; i < chars.Length; i++)
{
string lowerChar = chars[i].ToString().ToLower();
RetVal[i * 2] = lowerChar;
string upperChar = lowerChar.ToUpper();
if (lowerChar != upperChar)
RetVal[i * 2 + 1] = upperChar;
}
return RetVal;
}
public Command<string> InsertChar { get; set; }
public ObservableCollection<string> Data { get; set; }
public CharacterDataModel()
{
string[] Characters = GetSpecialCharsFromString(csCharacters);
Data = new ObservableCollection<string>(Characters);
InsertChar = new Command<string>(ExecuteCommand);
}
private void ExecuteCommand(string data)
{
MessageBox.Show(data);
}
}
public class Command : ICommand
{
public Action Action { get; set; }
public string DisplayName { get; set; }
public void Execute(object parameter)
{
if (Action != null)
Action();
}
public bool CanExecute(object parameter) => IsEnabled;
private bool _isEnabled = true;
public bool IsEnabled
{
get { return _isEnabled; }
set
{
_isEnabled = value;
if (CanExecuteChanged != null)
CanExecuteChanged(this, EventArgs.Empty);
}
}
public event EventHandler CanExecuteChanged;
public Command(Action action)
{
Action = action;
}
}
public class Command<T> : ICommand
{
public Action<T> Action { get; set; }
public void Execute(object parameter)
{
if (Action != null && parameter is T)
Action((T)parameter);
}
public bool CanExecute(object parameter)
{
return IsEnabled;
}
private bool _isEnabled = true;
public bool IsEnabled
{
get { return _isEnabled; }
set
{
_isEnabled = value;
if (CanExecuteChanged != null)
CanExecuteChanged(this, EventArgs.Empty);
}
}
public event EventHandler CanExecuteChanged;
public Command(Action<T> action)
{
Action = action;
}
}