简体   繁体   English

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

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

Lately ive been trying to make a grid that uses my UserControls to fill it in. The only problem i've encountered is that I cant use the WPF Binding stuff to link the user controls to my grid, making it for me very hard to nicely place them in the grid. 最近,我一直试图制作一个使用我的UserControls填充的网格。我遇到的唯一问题是我无法使用WPF Binding东西将用户控件链接到我的网格,这对我来说很难做到将它们放在网格中。 My question: How can i bind the attributes in my ViewModel (which are stored in the Block class, which my ViewModel has an object of), to my UserControl Block, allowing it to use those variables (the X and Y, which are the row and column of the grid, position)? 我的问题:如何将ViewModel中的属性(存储在ViewModel拥有对象的Block类中)绑定到UserControl Block,允许它使用这些变量(X和Y,即网格的行和列,位置)?

Here is the code of my user control: 这是我的用户控件的代码:

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>

Here is the ViewModel and Model class of the UserControl: 这是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()
    {

    }
}

Then following up we have my Window: 然后跟进我们的窗口:

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>

Thanks in advance, Nick van der Meij 在此先感谢Nick Van der Meij

Got it to work based on knowledge found here and here . 根据在这里这里找到的知识使它工作。 It is not pretty but this seems to be the only way it will work. 它不是很漂亮,但这似乎是它起作用的唯一方法。

You did not share the MainViewModel (I guess because it was not necessary for the quick sample you gave). 您没有共享MainViewModel (我想是因为您提供的快速示例没有必要)。 But since I needed it for binding and you will most probably work with it, here is my quick version: 但是由于我需要它进行绑定,并且您很可能会使用它,因此这里是我的快速版本:

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

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

You need to wrap the grid in an ItemsControl and use the ItemContainerStyle for binding the Grid.Column and Grid.Row : 您需要将网格包装在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>

The BlockView now looks like this: 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