Я работаю над оверлейным приложением, которое имеет ряд интерактивных элементов, реализованных в виде пользовательских элементов управления внутри прозрачного родительского окна.
Я хочу привязать к позиции этих (перетаскиваемых) пользовательских элементов управления чтобы сохранить их как пользовательские настройки
Вещи, которые я пробовал:
- привязать Margin к свойству Thickness, которое не обновляется при перемещении элемента управления
- привязка Canvas.Left / Top непосредственно к свойствам настроек (можно найти как комментарий в xaml), которые вообще не работают
Родительское окно:
<Window
x:Class="PoeSuite.Overlay"
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:local="clr-namespace:PoeSuite.Views"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:p="clr-namespace:PoeSuite.Properties"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:il="clr-namespace:Microsoft.Expression.Interactivity.Layout;assembly=Microsoft.Expression.Interactions"
AllowsTransparency="True"
Background="{x:Null}"
DataContext="{Binding OverlayCanvas, Source={StaticResource Locator}}"
Deactivated="Window_Deactivated"
Activated="Window_Activated"
SourceInitialized="Window_SourceInitialized"
ShowInTaskbar="False"
Visibility="{Binding ShouldBeVisible, Mode=TwoWay, Converter={StaticResource BoolToVis}}"
WindowState="Maximized"
WindowStyle="None"
mc:Ignorable="d">
<Grid>
<!--
Canvas.Left="{Binding Source={x:Static p:Settings.Default}, Path=IncomingOverlayX, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Canvas.Top="{Binding Source={x:Static p:Settings.Default}, Path=IncomingOverlayY, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
-->
<local:IncomingRequests
Margin="{Binding RelativeSource={RelativeSource AncestorType=Window, Mode=FindAncestor, AncestorLevel=1}, Path=DataContext.IncomingOverlayPosition}">
<i:Interaction.Behaviors>
<il:MouseDragElementBehavior />
</i:Interaction.Behaviors>
</local:IncomingRequests>
</Grid>
</Window>
Контроль пользователя:
<UserControl
x:Class="PoeSuite.Views.IncomingRequests"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converters="clr-namespace:PoeSuite.Views.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Name="incomingRequestsWindow"
DataContext="{Binding IncomingRequests, Source={StaticResource Locator}}"
Visibility="{Binding ShouldBeVisible, Mode=TwoWay, Converter={StaticResource BoolToVis}}"
mc:Ignorable="d">
<Grid>
<TabControl
ItemsSource="{Binding ActiveRequests, Mode=TwoWay}"
SelectedItem="{Binding SelectedTab, Mode=OneWayToSource}">
<TabControl.Resources>
<converters:ItemsControlIndexConverter x:Key="IndexConverter" />
<converters:BooleanToColorConverter x:Key="BooleanToColor" />
</TabControl.Resources>
<TabControl.ItemTemplate>
<DataTemplate>
<Grid>
<StackPanel Orientation="Horizontal">
<TextBlock
MaxWidth="50"
Foreground="{Binding PlayerJoinedArea, Converter={StaticResource BooleanToColor}}"
Text="{Binding ItemName}">
</TextBlock>
<Button
Command="{Binding RelativeSource={RelativeSource AncestorType=UserControl, Mode=FindAncestor, AncestorLevel=1}, Path=DataContext.CloseTabCommand}"
CommandParameter="{Binding}"
Content="x" />
</StackPanel>
</Grid>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<Grid>
<TextBlock Text="{Binding PlayerName, Mode=OneWay}" />
<Border BorderThickness="5" BorderBrush="AliceBlue">
<DockPanel
Grid.Row="1"
Width="Auto"
Height="20">
<Button
Width="20"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Command="{Binding RelativeSource={RelativeSource AncestorType=UserControl, Mode=FindAncestor, AncestorLevel=1}, Path=DataContext.SendInviteCommand}"
Content="+" />
...
</DockPanel>
</Border>
</Grid>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
</Grid>
</UserControl>
и соответствующий ViewModel :
public class OverlayViewModel : ViewModelBase
{
private bool _shouldBeVisible;
public bool ShouldBeVisible
{
get
{
return _shouldBeVisible;
}
set
{
_shouldBeVisible = value;
RaisePropertyChanged(nameof(ShouldBeVisible));
}
}
public Thickness IncomingOverlayPosition
{
get
{
return new Thickness(Properties.Settings.Default.IncomingOverlayX,
Properties.Settings.Default.IncomingOverlayY, 555, 555);
}
set
{
Properties.Settings.Default.IncomingOverlayX = value.Left;
Properties.Settings.Default.IncomingOverlayY = value.Top;
RaisePropertyChanged(nameof(IncomingOverlayPosition));
}
}
public OverlayViewModel()
{
if (IsInDesignMode)
_shouldBeVisible = true;
}
}