简体   繁体   English

将字符串项绑定到 xaml 中字符串的依赖属性列表

[英]Binding string items to a dependency property list of strings in xaml

I have a list of strings defined as a dependency property.我有一个定义为依赖属性的字符串列表。 I am assigning the values of the list's items via xaml.我通过 xaml 分配列表项的值。 I can assign literal string values, but I do not know how to bind those values to data from viewmodel.我可以分配文字字符串值,但我不知道如何将这些值绑定到来自 viewmodel 的数据。

public static readonly DependencyProperty StringArgsProperty = DependencyProperty.Register(
        "StringArgs", typeof(List<string>), typeof(GameTextBlock), new FrameworkPropertyMetadata(new List<string>()));

    public List<string> StringArgs
    {
        get { return (List<string>)GetValue(StringArgsProperty); }
        set { SetValue(StringArgsProperty, value); }
    }

Here's how I can bind items to said list currently:这是我目前如何将项目绑定到所述列表的方法:

<common:GameTextBlock.StringArgs>
  <sys:String>arg1</sys:String>
  <sys:String>arg2</sys:String>
</common:GameTextBlock.StringArgs>

What I am trying to do is replace arg1/arg2 with values from ViewModel.我想要做的是将 arg1/arg2 替换为 ViewModel 中的值。 If I wasn't assigning to the list's items I could do "{Binding NameOfField}".如果我没有分配给列表的项目,我可以执行“{Binding NameOfField}”。

I do not want to create the whole list in ViewModel and bind the list, because I want to be able to pick and choose the items using only xaml.我不想在 ViewModel 中创建整个列表并绑定列表,因为我希望能够仅使用 xaml 来挑选和选择项目。 Can this be achieved?这可以实现吗?

EDIT: A more clear example of what I want to achieve:编辑:我想要实现的更清楚的例子:

public class ViewModel
{
   public string Item1 {get; set;}
   public string Item2 {get; set;}
   public string Item3 {get; set;}
}

And then I want to be able to use them in one xaml containing multiple GameTextBlocks like this:然后我希望能够在一个包含多个 GameTextBlocks 的 xaml 中使用它们,如下所示:

<GameTextBlock x:Name = "txt1" > 
<GameTextBlock.StringArgs>
  <sys:String>{Binding VMItem1}</sys:String>
  <sys:String>{Binding VMItem3}</sys:String>
</GameTextBlock.StringArgs>
</GameTextBlock>

<GameTextBlock x:Name = "txt2" > 
<GameTextBlock.StringArgs>
  <sys:String>{Binding VMItem1}</sys:String>
  <sys:String>{Binding VMItem2}</sys:String>
</GameTextBlock.StringArgs>
</GameTextBlock>

<GameTextBlock x:Name = "txt3" > 
<GameTextBlock.StringArgs>
  <sys:String>{Binding VMItem1}</sys:String>
</GameTextBlock.StringArgs>
</GameTextBlock>

Static data on a xaml page cannot change. xaml 页面上的 Static 数据无法更改。 Move the list structures to the code behind and on the change handler of the dependency property move the data as needed to the property lists.将列表结构移动到代码后面和依赖属性的更改处理程序上,根据需要将数据移动到属性列表。 Regardless, this is how it should be done.无论如何,这就是它应该这样做的方式。

If you need two way transfer, then you will need more code behind to move the data from the control lists on the page back to the storage;如果您需要双向传输,那么您将需要更多代码将数据从页面上的控制列表移回存储; still, this can be used as a template.不过,这可以用作模板。

Control Code behind控制代码

Data Lists数据列表

Here are the lists on the custom control to be split out to:以下是要拆分为的自定义控件上的列表:

public partial class ShowDependency : UserControl, INotifyPropertyChanged
{
 
private List<string> _Text1;

public List<string> Text1
{
    get { return _Text1; }
    set { _Text1 = value; OnPropertyChanged(nameof(Text1)); }
}

private List<string> _Text2;

public List<string> Text2
{
    get { return _Text2; }
    set { _Text2 = value; OnPropertyChanged(nameof(Text2)); }
}
Dependency property with PropertyChanged Handler具有 PropertyChanged 处理程序的依赖属性

Here is the dependency property which will hold the incoming list from the VM这是包含来自 VM 的传入列表的依赖项属性

#region public List<string> Storage
/// <summary>Storage is a transfer from the Main VM</summary>
public List<string> Storage
{
    get => (List<string>)GetValue(StorageProperty);
    set => SetValue(StorageProperty, value);
}

/// <summary>Identifies the Storage dependency property.</summary>
public static readonly DependencyProperty StorageProperty =
    DependencyProperty.Register(
        "Storage",
        typeof(List<string>),
        typeof(ShowDependency),
        new PropertyMetadata(null, OnStoragePropertyChanged));
Change Handler变更处理程序

Once bound, it smurfs the data into the lists.一旦绑定,它会将数据添加到列表中。

/// <summary>StorageProperty property changed handler.</summary>
/// <param name="d">ShowDependency that changed its Storage.</param>
/// <param name="e">Event arguments.</param>
private static void OnStoragePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    if (d is ShowDependency source)
    {
        var value = (List<string>)e.NewValue;

        if (value != null)
        {
            var l1 = new List<string>();
            var l2 = new List<string>();
            int count = 1;
            foreach (var item in value)
                if ((count++ % 2) == 0)
                    l1.Add(item);
                else 
                    l2.Add(item);

            source.Text1 = l1;
            source.Text2 = l2;
        }

    }
}
#endregion public List<string> Storage
Binding List of Strings on Main VM主虚拟机上的字符串绑定列表
 new List<string>() { "Alpha", "Baker", "Tango", "Omega" }
Custom Control Page自定义控制页面
<UserControl x:Class="ExamplesInWPF.Controls.ShowDependency"
             ...
             d:DesignHeight="450" d:DesignWidth="800"
             x:Name="MyUserControl">
    <StackPanel Orientation="Vertical">
        <ListBox Margin="6" ItemsSource="{Binding Text1, ElementName=MyUserControl}"/>
        <ListBox Margin="6" ItemsSource="{Binding Text2, ElementName=MyUserControl}"/>        
    </StackPanel>
</UserControl>
Result结果

在此处输入图像描述


As an aside I have always used these Control dependency property snippets顺便说一句,我一直使用这些 Control 依赖属性片段

Helpful Silverlight Snippets 有用的 Silverlight 片段

Disregard the Silverlight part, they are still good and work up to.Net 6 Xaml/WPF.忽略 Silverlight 部分,它们仍然很好,并且适用于.Net 6 Xaml/WPF。

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

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