0

我正在尝试创建具有以下要求的 UserControl。

用户控件包含一个网格视图,在侧网格视图中,我需要添加一个按钮元素。因此,想法是:- 如果通过向 ItemSource 提供集合在任何其他页面中使用用户控件,则应生成按钮列表,并且 Button 内容值应该是 Itemsource 集合中存在的类型的属性值之一。

我是 Windows 商店应用程序编程的新手。我试图通过创建依赖属性来公开 gridview ItemSources 属性,以便可以映射任何类型的 ObservableCollection 并尝试公开依赖属性以绑定到按钮内容属性。但无法达到同样的效果。如果您能指出一个执行相同操作的示例应用程序,我将不胜感激。

提前非常感谢。

4

1 回答 1

0

here is a small sample (i hope that's what you wanna do)...

EDIT: I finally edited my answer to provide the property which takes the property path. IF ANYONE HAS ANOTHER SOLUTION FOR THIS QUESTION, PLEASE LET ME KNOW!

Add a dependency property for the binding path:

First we create a dummy model which provides the title for our buttons:

public class SampleModel
{
    public string Title { get; set; }
}

Then, the usercontrol. The important thing here is the ItemsSource-Binding (ElementName = UserControl). Otherwise you'll bind to the UserControlItemsSource in the Parent-DataContext.

EDIT: The button has changed since my last answer!

<UserControl
x:Class="StackOverflow.ListUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:StackOverflow"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400"
x:Name="SampleUserControl">

<Grid>
    <ListView ItemsSource="{Binding UserControlItemsSource, ElementName=SampleUserControl}" Background="DeepSkyBlue" SelectionMode="None">
        <ListView.ItemTemplate>
            <DataTemplate>
                <Button Loaded="FrameworkElement_OnLoaded"/>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</Grid>
</UserControl>

... and the usercontrol's code-behind including the UsercontrolItemsSource:

EDIT: i added the dependency property BindingPropertyPath and the FrameworkElement_OnLoaded method since my last answer.

public sealed partial class ListUserControl : UserControl
{
    public ObservableCollection<SampleModel> UserControlItemsSource
    {
        get { return (ObservableCollection<SampleModel>)GetValue(UserControlItemsSourceProperty); }
        set { SetValue(UserControlItemsSourceProperty, value); }
    }

    // Using a DependencyProperty as the backing store for UserControlItemsSource.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty UserControlItemsSourceProperty =
        DependencyProperty.Register("UserControlItemsSource", typeof(ObservableCollection<SampleModel>), typeof(ListUserControl), new PropertyMetadata(null));


    public string BindingPropertyPath
    {
        get { return (string)GetValue(BindingPropertyPathProperty); }
        set { SetValue(BindingPropertyPathProperty, value); }
    }

    // Using a DependencyProperty as the backing store for BindingPropertyPath.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty BindingPropertyPathProperty =
        DependencyProperty.Register("BindingPropertyPath", typeof(string), typeof(ListUserControl), new PropertyMetadata(string.Empty));


    public ListUserControl()
    {
        this.InitializeComponent();
    }

    private void FrameworkElement_OnLoaded(object sender, RoutedEventArgs e)
    {
        Button button = sender as Button;
        Binding contentBinding = new Binding();
        contentBinding.Path = new PropertyPath(this.BindingPropertyPath);
        button.SetBinding(Button.ContentProperty, contentBinding);
    }
}

Now we add the usercontrol to our main page (ListPageHost):

EDIT: Set the new dependency property BindingPropertyPath to the name of the property of the ItemsSource that you wanna use for the button.

<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>

    <Button Grid.Row="0" Content="Add Item to ItemsSource" Click="ButtonBase_OnClick"></Button>
    <local:ListUserControl Grid.Row="1" UserControlItemsSource="{Binding SampleCollection}" BindingPropertyPath="Title"/>
</Grid>

In the mainpage's code-behind, we declare our mainpage-viewmodel (ListPageHostViewModel):

public class ListPageHostViewModel
{
    private readonly ObservableCollection<SampleModel> _sampleCollection = new ObservableCollection<SampleModel>();

    public ObservableCollection<SampleModel> SampleCollection
    {
        get { return _sampleCollection; }
    }
}

... and the MainPage's (ListPageHost) code behind:

public sealed partial class ListPageHost : Page
{
    public ListPageHost()
    {
        this.InitializeComponent();
        this.DataContext = new ListPageHostViewModel();
    }

    /// <summary>
    /// Invoked when this page is about to be displayed in a Frame.
    /// </summary>
    /// <param name="e">Event data that describes how this page was reached.  The Parameter
    /// property is typically used to configure the page.</param>
    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
    }

    private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
    {
        var vm = this.DataContext as ListPageHostViewModel;
        if (vm != null)
        {
            vm.SampleCollection.Add(new SampleModel() { Title = string.Format("new item {0}", DateTime.Now.Ticks)});
        }
    }
}

Hope that's what you're looking for. If you have any questions - let me know. Regards, Alex

于 2013-06-21T08:45:31.707 回答