Моя заявка оформлена следующим образом:
Модели:
Торговля
Просмотры:
TradeManagerView
TradeView <Настраиваемый пользовательский контроль </em>
ViewModels:
TradeManagerViewModel
У TradeManagerView
есть DataGrid
с ItemsSource
, установленным на ObservableCollection<Trade>
в TradeManagerViewModel
, а его шаблон данных - пользовательский элемент управления TradeView
.
Модель Trade
имеет свойство TradeDirection
, равное In
или Out
. TradeManagerViewModel
представляет два набора ObservableCollection<Button>
, по одному на каждый TradeDirection
. Эти кнопки настраиваются пользователем во время выполнения, поэтому они не создаются в XAML. Я изо всех сил пытаюсь связать ItemsControl
в TradeView
с кнопками в TradeManagerViewModel
, поскольку его контекст данных является экземпляром Trade
, который предоставляется DataGrid ItemsSource
.
I для начала попробовал следующее, но ни одна из них не работает. Я использую Caliburn.Micro, который устанавливает DataContext View в ViewModel во время выполнения.
<ItemsControl x:Name="TradeActions" ItemsSource="{Binding InboundTradeActions, ElementName=TradeManager}">
<ItemsControl x:Name="TradeActions" ItemsSource="{Binding InboundTradeActions, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}">
Как уже упоминалось, мне нужно привязать к правильной коллекции (т.е. InboundTradeActions
или OutboundTradeActions
) на основе Trade.TradeDirection
, поэтому вышеупомянутое не сработает в любом случае. Я не уверен, будет ли это лучше всего работать в XAML с DataTrigger? или создать третье свойство, которое возвращает правильную коллекцию. Но каким-то образом это свойство должно знать TradeDirection
для DataContext относительного TradeView
.
Надеюсь, все это имеет смысл. Пожалуйста, дайте мне знать, если нет, и я исправлю его.
Торговый класс
internal class Trade : PropertyChangedBase
{
public enum Direction { In, Out };
private ObservableCollection<Button> tradeActions = new ObservableCollection<Button>();
public ObservableCollection<Button> TradeActions
{
get { return tradeActions; }
set
{
tradeActions = value;
NotifyOfPropertyChange();
}
}
public Direction TradeDirection
{
get { return tradeDirection; }
set
{
tradeDirection = value;
if (value == Direction.In)
{
InArrowVisibility = Visibility.Visible;
OutArrowVisibility = Visibility.Hidden;
}
else
{
InArrowVisibility = Visibility.Hidden;
OutArrowVisibility = Visibility.Visible;
}
NotifyOfPropertyChange();
}
}
public Visibility InArrowVisibility { get; set; }
public Visibility OutArrowVisibility { get; set; }
// Other properties removed to shorten
}
TradeManagerView
<Window x:Class="ExaltedTrade.Views.TradeManagerView"
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:ExaltedTrade.Views"
mc:Ignorable="d"
Title="Trade Manager" Height="450" Width="400"
WindowStartupLocation="Manual"
Style="{StaticResource TradeManagerWindow}"
Top="{Binding WindowTop, Mode=TwoWay}"
Left="{Binding WindowLeft, Mode=TwoWay}"
x:Name="TradeManager">
<Grid>
<DataGrid x:Name="ActiveTrades"
AutoGenerateColumns="False"
IsReadOnly="True"
HeadersVisibility="None"
GridLinesVisibility="None"
Style="{StaticResource TradeManagerDataGrid}"
CellStyle="{StaticResource TradeControlCell}"
ItemsSource="{Binding ActiveTrades}">
<DataGrid.Columns>
<DataGridTemplateColumn Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<local:TradeView /> <!-- This is the custom UserControl -->
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
TradeView
Я включил иерархию UserControl, но удалил лишние элементы управления для сокращения.
<UserControl x:Class="ExaltedTrade.Views.TradeView"
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:ExaltedTrade.Views"
mc:Ignorable="d"
d:DesignHeight="150" d:DesignWidth="500" Style="{StaticResource TradeView}">
<Grid>
<Expander x:Name="Expander" HorizontalAlignment="Stretch" Margin="0,0,0,0" VerticalAlignment="Top" IsExpanded="True">
<Expander.Header>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*" /><!-- Player Name -->
<ColumnDefinition Width="14" /><!-- Trade Direction -->
<ColumnDefinition Width="1*" /><!-- Quantity -->
<ColumnDefinition Width="16" /><!-- Currency Icon -->
<ColumnDefinition Width="26" /><!-- Timer -->
<ColumnDefinition Width="26" /><!-- Invite -->
<ColumnDefinition Width="26" /><!-- Trade -->
<ColumnDefinition Width="26" /><!-- Kick -->
<ColumnDefinition Width="26" /><!-- Whisper -->
<ColumnDefinition Width="26" /><!-- Close -->
</Grid.ColumnDefinitions>
<!-- Some controls removed to shorten -->
</Expander.Header>
<Expander.Content>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="16" />
<ColumnDefinition Width="22" />
</Grid.ColumnDefinitions>
<!-- Some controls removed to shorten -->
<!-- BINDING IS HERE -->
<ItemsControl x:Name="TradeActions" Grid.Column="0" Grid.Row="1" ItemsSource="{Binding InboundTradeActions, ElementName=TradeManager}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Style="{StaticResource TradeActions}" IsItemsHost="True" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Grid>
</Expander.Content>
</Expander>
</Grid>
</UserControl>
TradeManagerViewModel
class TradeManagerViewModel : PropertyChangedBase, IHandle<string>
{
private ObservableCollection<Trade> activeTrades = new ObservableCollection<Trade>();
public ObservableCollection<Trade> ActiveTrades
{
get
{
return activeTrades;
}
set
{
activeTrades = value;
NotifyOfPropertyChange();
}
}
public static ObservableCollection<Button> InboundTradeActions { get; set; } = new ObservableCollection<Button>();
public static ObservableCollection<Button> OutboundTradeActions { get; set; } = new ObservableCollection<Button>();
public TradeManagerViewModel()
{
//TODO: Remove the test Trades
ObservableCollection<Trade> temp = new ObservableCollection<Trade> { new Trade("ExamplePlayer", Trade.Direction.In) };
temp.Add(new Trade("AnotherExamplePlayer", Trade.Direction.Out));
ActiveTrades = temp;
SetupTradeActions();
}
private void SetupTradeActions()
{
// TradeActions for inbound Trades
InboundTradeActions.Clear(); // Remove any existing TradeAction buttons just in case
foreach (TradeAction tAction in AppSettings.GetSingleton().InboundTradeActions)
{
Button action = new Button
{
Content = tAction.ButtonText,
//action.Command = ; //TODO: Need to implement an ICommand to link the method to the buttons
CommandParameter = tAction
};
InboundTradeActions.Add(action);
}
// TradeActions for outbound Trades
OutboundTradeActions.Clear(); // Remove any existing TradeAction buttons just in case
foreach (TradeAction tAction in AppSettings.GetSingleton().OutboundTradeActions)
{
Button action = new Button
{
Content = tAction.ButtonText,
//action.Command = ; //TODO: Need to implement an ICommand to link the method to the buttons
CommandParameter = tAction
};
OutboundTradeActions.Add(action);
}
}
}