Apoc
Well-Known Member
- Joined
- Jan 16, 2010
- Messages
- 2,790
ORIGINAL POST HERE: https://www.thebuddyforum.com/exilebuddy-forum/exilebuddy-guides/183512-code-xaml-wpf-guis.html
This guide will cover the process of using the new code-behind/XAML support offered in Exilebuddy. Starting with Beta #932 and Release #72, Exilebuddy now properly supports code-behind/xaml in the WPF guis dynamically loaded.
This means users no longer have to code manual bindings for controls or event handlers, which greatly simplifies GUI development and makes it more manageable.
To get started, please refer to the How to Setup a Project for Exilebuddy to setup a project to test the new functionality. For this guide, I'll refer to using the provided ExampleBot code included with the bot. You'll want to copy all the files of ExampleBot into a new project and setup References so it compiles. Once that is done, you're ready to being.
The current XAML loading method can be seen by looking at the implementation of the Control property in ExampleBot.cs.
With this method, we manually load and parse a XAML file, and then setup manual bindings for the controls and event handlers. No code-behind mechanics are supported this way.
1. First, we will want to add a new UserControl to ExampleBot to get the associated code-behind files generated normally. Right click on the project name in the Solution Explorer and choose "Add" -> "User Control...".
2. In the new window that opens, type in a new, different name for new user control and select "User Control (WPF)". For this guide, I'll be using "ExampleBotGui.xaml"
3. Click Add. You will now have an "ExampleBotGui.xaml" file and an "ExampleBotGui.xaml.cs" file added to the project.
4. Normally, you'd just develop your gui and code-behind logic as you would with any WPF application. For this guide, we'll be copying the old gui code and making a few adjustments. NOTE: The ListBox and ComboBox controls do not have bindings for the sake of the example. Here are the contents of the modified files we will be testing with:
ExampleBotGui.xaml
ExampleBotGui.xaml.cs
5. Finally, the code for the Control property needs to be changed. We simply create a new object of the gui and return it:
6. Delete the old "SettingsGui.xaml" file because it will no longer be needed. Compile the project and make sure there are no errors.
7. At this point, files need to be copied into the bot folder for testing. Delete the contents of the Exilebuddy Bots\ExampleBot folder for a clean start.
8. Run the bot. If everything was done correctly, the bot should load up without any errors. When switching to the Settings tab for ExampleBot, you should have working bindings and event handlers.
That concludes this guide. Hopefully, GUI development is a lot more natural and easier to work with now.
This guide will cover the process of using the new code-behind/XAML support offered in Exilebuddy. Starting with Beta #932 and Release #72, Exilebuddy now properly supports code-behind/xaml in the WPF guis dynamically loaded.
This means users no longer have to code manual bindings for controls or event handlers, which greatly simplifies GUI development and makes it more manageable.
To get started, please refer to the How to Setup a Project for Exilebuddy to setup a project to test the new functionality. For this guide, I'll refer to using the provided ExampleBot code included with the bot. You'll want to copy all the files of ExampleBot into a new project and setup References so it compiles. Once that is done, you're ready to being.
The current XAML loading method can be seen by looking at the implementation of the Control property in ExampleBot.cs.
Code:
/// <summary> The bot's settings control. This will be added to the Exilebuddy Settings tab.</summary>
public UserControl Control
{
get
{
using (var fs = new FileStream(@"Bots\ExampleBot\SettingsGui.xaml", FileMode.Open))
{
var root = (UserControl) XamlReader.Load(fs);
// TODO: Your settings binding here.
if (!Wpf.SetupTextBoxBinding(root, "TestTextBox", "TestTextBoxValue",
BindingMode.TwoWay, ExampleBotSettings.Instance))
{
Log.DebugFormat("[SettingsControl] SetupTextBoxBinding failed for 'TestTextBox'.");
throw new Exception("The SettingsControl could not be created.");
}
if (!Wpf.SetupCheckBoxBinding(root, "TestCheckBox", "TestCheckBoxValue",
BindingMode.TwoWay, ExampleBotSettings.Instance))
{
Log.DebugFormat("[SettingsControl] SetupCheckBoxBinding failed for 'TestCheckBox'.");
throw new Exception("The SettingsControl could not be created.");
}
if (!Wpf.SetupLabelBinding(root, "TestLabel", "TestLabelValue",
BindingMode.TwoWay, ExampleBotSettings.Instance))
{
Log.DebugFormat("[SettingsControl] SetupLabelBinding failed for 'TestLabel'.");
throw new Exception("The SettingsControl could not be created.");
}
if (!Wpf.SetupListBoxItemsBinding(root, "TestListBox", "TestListBoxValue",
BindingMode.OneWay, ExampleBotSettings.Instance))
{
Log.DebugFormat("[SettingsControl] SetupListBoxBinding failed for 'TestListBox'.");
throw new Exception("The SettingsControl could not be created.");
}
if (!Wpf.SetupListBoxSelectedItemBinding(root, "TestListBox", "TestListBoxSelectedValue",
BindingMode.TwoWay, ExampleBotSettings.Instance))
{
Log.DebugFormat("[SettingsControl] SetupListBoxSelectedItemBinding failed for 'TestListBox'.");
throw new Exception("The SettingsControl could not be created.");
}
if (!Wpf.SetupComboBoxSelectedItemBinding(root, "TestComboBox", "TestComboBoxSelectedValue",
BindingMode.TwoWay, ExampleBotSettings.Instance))
{
Log.DebugFormat("[SettingsControl] SetupComboBoxSelectedItemBinding failed for 'TestComboBox'.");
throw new Exception("The SettingsControl could not be created.");
}
if (!Wpf.SetupComboBoxItemsBinding(root, "TestComboBox", "AllTestComboBoxValues",
BindingMode.OneWay, ExampleBotSettings.Instance))
{
Log.DebugFormat("[SettingsControl] SetupComboBoxItemsBinding failed for 'TestComboBox'.");
throw new Exception("The SettingsControl could not be created.");
}
// TODO: Your settings event handlers here.
return root;
}
}
}
With this method, we manually load and parse a XAML file, and then setup manual bindings for the controls and event handlers. No code-behind mechanics are supported this way.
1. First, we will want to add a new UserControl to ExampleBot to get the associated code-behind files generated normally. Right click on the project name in the Solution Explorer and choose "Add" -> "User Control...".

2. In the new window that opens, type in a new, different name for new user control and select "User Control (WPF)". For this guide, I'll be using "ExampleBotGui.xaml"

3. Click Add. You will now have an "ExampleBotGui.xaml" file and an "ExampleBotGui.xaml.cs" file added to the project.

4. Normally, you'd just develop your gui and code-behind logic as you would with any WPF application. For this guide, we'll be copying the old gui code and making a few adjustments. NOTE: The ListBox and ComboBox controls do not have bindings for the sake of the example. Here are the contents of the modified files we will be testing with:
ExampleBotGui.xaml
Code:
<UserControl x:Class="ExampleBot.ExampleBotGui"
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:settingsPath="clr-namespace:ExampleBot"
mc:Ignorable="d"
d:DesignHeight="440" d:DesignWidth="627">
<Grid Background="LightSteelBlue" x:Name="Root" DataContext="{x:Static settingsPath:ExampleBotSettings.Instance}">
<ScrollViewer VerticalScrollBarVisibility="Auto">
<StackPanel>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Content="TestTextBox: " Margin="3,5,3,1" ToolTipService.ToolTip="This is a test TextBox."/>
<TextBox Name="TestTextBox" Grid.Row="0" Grid.Column="1" Margin="3" Text="{Binding Path=TestTextBoxValue, Mode=TwoWay}"/>
<Label Grid.Row="1" Grid.Column="0" Content="TestCheckBox: " Margin="3,5,3,1" ToolTipService.ToolTip="This is a test CheckBox."/>
<CheckBox Name="TestCheckBox" Grid.Row="1" Grid.Column="1" Margin="3" IsChecked="{Binding Path=TestCheckBoxValue, Mode=TwoWay}" />
<Label Grid.Row="2" Grid.Column="0" Content="TestLabel: " Margin="3,5,3,1" ToolTipService.ToolTip="This is a test Label."/>
<Label Name="TestLabel" Grid.Row="2" Grid.Column="1" Margin="3" Content="{Binding Path=TestLabelValue, Mode=OneWay}"/>
<Label Grid.Row="3" Grid.Column="0" Content="TestListBox: " Margin="3,5,3,1" ToolTipService.ToolTip="This is a test ListBox."/>
<ListBox Name="TestListBox" Grid.Row="3" Grid.Column="1" Margin="3"/>
<Label Grid.Row="4" Grid.Column="0" Content="TestComboBox: " Margin="3,5,3,1" ToolTipService.ToolTip="This is a test ComboBox."/>
<ComboBox Name="TestComboBox" Grid.Row="4" Grid.Column="1" Margin="3"/>
<Button Name="TestButton" Grid.Row="5" Grid.Column="0" Content="TestButton: " Margin="3,5,3,1" Click="TestButton_OnClick" ToolTipService.ToolTip="This is a test Button."/>
</Grid>
</StackPanel>
</ScrollViewer>
</Grid>
</UserControl>
ExampleBotGui.xaml.cs
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using log4net;
using Loki.Utilities;
namespace ExampleBot
{
/// <summary>
/// Interaction logic for ExampleBotGui.xaml
/// </summary>
public partial class ExampleBotGui : UserControl
{
private static readonly ILog Log = Logger.GetLoggerInstanceForType();
public ExampleBotGui()
{
InitializeComponent();
}
private void TestButton_OnClick(object sender, RoutedEventArgs e)
{
Log.Info("The TestButton was clicked!");
}
}
}
5. Finally, the code for the Control property needs to be changed. We simply create a new object of the gui and return it:
Code:
/// <summary> The bot's settings control. This will be added to the Exilebuddy Settings tab.</summary>
public UserControl Control
{
get { return new ExampleBotGui(); }
}
6. Delete the old "SettingsGui.xaml" file because it will no longer be needed. Compile the project and make sure there are no errors.
7. At this point, files need to be copied into the bot folder for testing. Delete the contents of the Exilebuddy Bots\ExampleBot folder for a clean start.
- Copy all "cs" files to the ExampleBot folder. This includes the "xaml.cs" files.
- Inside the "obj\Release" folder (or Debug if you're building in debug) copy all "baml" and "g.cs" (not g.i.cs) files to the ExampleBot folder.

8. Run the bot. If everything was done correctly, the bot should load up without any errors. When switching to the Settings tab for ExampleBot, you should have working bindings and event handlers.

That concludes this guide. Hopefully, GUI development is a lot more natural and easier to work with now.