繁体   English   中英

WPF和MVVM:如何在UserControl中使用附加属性

[英]WPF and MVVM: How use attached properties in my UserControl

最近,我一直试图制作一个使用我的UserControls填充的网格。我遇到的唯一问题是我无法使用WPF Binding东西将用户控件链接到我的网格,这对我来说很难做到将它们放在网格中。 我的问题:如何将ViewModel中的属性(存储在ViewModel拥有对象的Block类中)绑定到UserControl Block,允许它使用这些变量(X和Y,即网格的行和列,位置)?

这是我的用户控件的代码:

namespace Mortal_Pets.Views
public partial class BlockView : UserControl
{

    public BlockView()
    {
        InitializeComponent();
        DataContext = new BlockViewModel();
    }
}

<UserControl x:Class="Mortal_Pets.Views.BlockView"
         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" 
         d:DesignHeight="30" d:DesignWidth="30">
<Canvas Background="{Binding Block.Color}" Grid.Row="{Binding Path=Block.XPosition}"  Grid.Column="{Binding Path=Block.YPosition}">

</Canvas>

这是UserControl的ViewModel和Model类:

class BlockViewModel
{
    public Block Block { get; set; }

    public BlockViewModel()
    {
        Block = new Block();
        Block.XPosition = 5; //Does Not Work, But this is how i'd like to have it
        Block.YPosition = 5; //Does Not Work, But this is how i'd like to have it
        Block.Color = new SolidColorBrush(Colors.Black);
    }
}

class Block
{
    public int XPosition { get; set; }
    public int YPosition { get; set; }
    public Brush Color { get; set; }

    public Block()
    {

    }
}

然后跟进我们的窗口:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new MainViewModel();
    }

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        BlockView view = new BlockView();
        view.SetValue(Grid.ColumnProperty, 5); //This does work, but is ugly and not really usefull for what i intend to do with it
        view.SetValue(Grid.RowProperty, 5); //This does work, but is ugly and not really usefull for what i intend to do with it
        BoardGrid.Children.Add(view); //This does work, but is ugly and not really usefull for what i intend to do with it
    }
}

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:Mortal_Pets.Views" x:Class="Mortal_Pets.Views.MainWindow"
    Title="MainWindow" Height="700" Width="600"
Loaded="Window_Loaded">
<Grid x:Name="BoardGrid" Margin="10,50,10,10" Width="500" Height="500">
    <Grid.RowDefinitions>
        <RowDefinition Height="25"/>
        <RowDefinition Height="25"/>
        <RowDefinition Height="25"/>
        <RowDefinition Height="25"/>
        <RowDefinition Height="25"/>
        <RowDefinition Height="25"/>
        <RowDefinition Height="25"/>
        <RowDefinition Height="25"/>
        <RowDefinition Height="25"/>
        <RowDefinition Height="25"/>
        <RowDefinition Height="25"/>
        <RowDefinition Height="25"/>
        <RowDefinition Height="25"/>
        <RowDefinition Height="25"/>
        <RowDefinition Height="25"/>
        <RowDefinition Height="25"/>
        <RowDefinition Height="25"/>
        <RowDefinition Height="25"/>
        <RowDefinition Height="25"/>
        <RowDefinition Height="25"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="25"/>
        <ColumnDefinition Width="25"/>
        <ColumnDefinition Width="25"/>
        <ColumnDefinition Width="25"/>
        <ColumnDefinition Width="25"/>
        <ColumnDefinition Width="25"/>
        <ColumnDefinition Width="25"/>
        <ColumnDefinition Width="25"/>
        <ColumnDefinition Width="25"/>
        <ColumnDefinition Width="25"/>
        <ColumnDefinition Width="25"/>
        <ColumnDefinition Width="25"/>
        <ColumnDefinition Width="25"/>
        <ColumnDefinition Width="25"/>
        <ColumnDefinition Width="25"/>
        <ColumnDefinition Width="25"/>
        <ColumnDefinition Width="25"/>
        <ColumnDefinition Width="25"/>
        <ColumnDefinition Width="25"/>
        <ColumnDefinition Width="25"/>
    </Grid.ColumnDefinitions>
    <Label x:Name="ComboCounter" Content="{Binding Game.ComboCounter}" HorizontalAlignment="Left" Margin="-2,-61,0,0" VerticalAlignment="Top" Width="95" Grid.ColumnSpan="4"/>

</Grid>

在此先感谢Nick Van der Meij

根据在这里这里找到的知识使它工作。 它不是很漂亮,但这似乎是它起作用的唯一方法。

您没有共享MainViewModel (我想是因为您提供的快速示例没有必要)。 但是由于我需要它进行绑定,并且您很可能会使用它,因此这里是我的快速版本:

class MainViewModel
{
    public List<BlockViewModel> Blocks { get; set; }

    public MainViewModel()
    {
        Blocks = new List<BlockViewModel> { new BlockViewModel() };
    }
}

您需要将网格包装在ItemsControl并使用ItemContainerStyle绑定Grid.ColumnGrid.Row

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="700" Width="600"
        xmlns:local="clr-namespace:WpfApplication1">

    <ItemsControl ItemsSource="{Binding Path=Blocks}">
        <ItemsControl.ItemContainerStyle>
            <Style>
                <Setter Property="Grid.Row" Value="{Binding Block.YPosition}" />
                <Setter Property="Grid.Column" Value="{Binding Block.XPosition}" />
            </Style>
        </ItemsControl.ItemContainerStyle>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <local:BlockView/>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Grid Margin="10,50,10,10" Width="500" Height="500" ShowGridLines="True">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="25"/>
                        <RowDefinition Height="25"/>
                        <RowDefinition Height="25"/>
                        <RowDefinition Height="25"/>
                        <RowDefinition Height="25"/>
                        <RowDefinition Height="25"/>
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="25"/>
                        <ColumnDefinition Width="25"/>
                        <ColumnDefinition Width="25"/>
                        <ColumnDefinition Width="25"/>
                        <ColumnDefinition Width="25"/>
                        <ColumnDefinition Width="25"/>
                    </Grid.ColumnDefinitions>
                </Grid>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
    </ItemsControl>    
</Window>

BlockView现在看起来像这样:

<UserControl x:Class="WpfApplication1.BlockView"
             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" d:DesignHeight="30" d:DesignWidth="30">    
    <Canvas Background="{Binding Block.Color}">
    </Canvas>
</UserControl>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM