C#xaml绑定到其他地方的属性

时间:2014-04-01 17:41:03

标签: c# xaml binding

假设您有一个项目列表,每个项目都有Id和Name属性。然后你有一个字典(一个单独的属性),它将id映射到价格。

public partial class MainWindow : Window
    {
        private IEnumerable<Comic> issues = new List<Comic>
        {
            new Comic() {Id = 5, Name = "Issue 1"},
            new Comic() {Id = 19, Name = "Issue 2"},
            new Comic() {Id = 3, Name = "Issue 3"},
            new Comic() {Id = 9, Name = "Issue 4"}
        };

        public Dictionary<int, decimal> Prices
        {
            get
            {
                return new Dictionary<int, decimal>()
                {
                    {5, 10.55M},
                    {19, 5.00M},
                    {3, 19.45M},
                    {9, 287.74M}

                };            
            }// end get
        }// end property Prices

        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = this;
        }

        public IEnumerable<Comic> ExpensiveIssues
        {
            get 
            {
                return issues;
            }
        }// end ExpensiveIssues()
    }// end MainWindow

    public class Comic
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

在用户界面中,您希望显示一个包含项目名称和价格的表格(按ID查找价格)。你会如何通过数据绑定来做到这一点?

<Window x:Class="LinqTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <ListView ItemsSource="{Binding ExpensiveIssues}" x:Name="viewNumbers" HorizontalAlignment="Left" Margin="137,52,0,0" VerticalAlignment="Top">
            <ListView.View>
                <GridView AllowsColumnReorder="True">
                    <GridViewColumn DisplayMemberBinding="{Binding Path=Name}" Header="Issue Name" Width="Auto" />
                    <GridViewColumn DisplayMemberBinding="{Binding Path=Prices[Id]}" Header="Price" Width="Auto" />
                </GridView>
            </ListView.View>
        </ListView>
    </Grid>
</Window>

我理解为什么“价格[Id]”不起作用('因为类似漫画中没有房产价格。但是我想从目前的背景中退一步,从主要价格中抢夺房产价格DataContext(MainWindow),然后通过ListView集合的当前迭代的Id属性查找价格。

我知道我可以把价格放在漫画课上,但这不是这个练习的重点。我知道在现实世界中我会需要访问这样的不同集合,并且我想知道如何做到这一点(或者如果真的有可能)。

我一直试图谷歌这没有运气,因为我还不知道正确的C#/ XAML术语来说明谷歌有用的问题。

3 个答案:

答案 0 :(得分:1)

这是使用Converter快速实施的实施方案。请注意,为了获得&#34;价格&#34;转换器中的字典,我使用MultiValueConverter,以便它也可以传递(以及Id)。

XAML:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:wpfApplication1="clr-namespace:WpfApplication1"
        Title="MainWindow" Height="350" Width="525"
        x:Name="MyWindow">
    <Grid>
        <Grid.Resources>
            <wpfApplication1:IdToPriceConverter x:Key="IdToPriceConverter" />
        </Grid.Resources>
        <ListView ItemsSource="{Binding ExpensiveIssues}" x:Name="viewNumbers" HorizontalAlignment="Left" Margin="137,52,0,0" VerticalAlignment="Top">
            <ListView.View>
                <GridView AllowsColumnReorder="True">
                    <GridViewColumn DisplayMemberBinding="{Binding Path=Name}" Header="Issue Name" Width="Auto" />
                    <GridViewColumn Header="Price" Width="Auto" >
                        <GridViewColumn.DisplayMemberBinding>
                            <MultiBinding Converter="{StaticResource IdToPriceConverter}">
                                <Binding Path="Id"/>
                                <Binding Path="DataContext.Prices" RelativeSource="{RelativeSource AncestorType=Window}"/>
                            </MultiBinding>
                        </GridViewColumn.DisplayMemberBinding>
                    </GridViewColumn>
                </GridView>
            </ListView.View>
        </ListView>
    </Grid>
</Window>

转换器:

namespace WpfApplication1
{
    public class IdToPriceConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            var id = values[0] is int ? (int) values[0] : -1;
            var prices = values[1] as Dictionary<int, decimal>;

            if (-1 != id)
            {
                if (null != prices)
                {
                    return prices[id].ToString(CultureInfo.InvariantCulture);
                }
            }
            return String.Empty;
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

如果您有任何问题,请与我们联系。

答案 1 :(得分:0)

您可以将Price添加为漫画类型的属性,而不是单独的价格词典,即

public class Comic
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
}

您的linq查询也会相应更改:

public IEnumerable<Comic> ExpensiveIssues
{
    get 
    {
        var result = from issue in issues where issue.Price >= 10 select issue;
        return result as IEnumerable<Comic>;
    }
}

在XAML中,然后将第二个网格列绑定到Price属性

答案 2 :(得分:0)

这是我认为你在Lambda中的意思。

var result = issues.Where(x => Prices.Any(y => y.Key == x.Id && y.Value > 10));

这将返回IEnumerable<Comic>,其中Comic.Id等于字典Key且值大于10

希望有所帮助