代码隐藏中的WPF绑定与手动更新

时间:2015-04-23 08:30:02

标签: c# wpf xaml code-behind

所以,我有一个UserControl,它显示从文件对象中提取的客户的基本信息。

控件如下所示:

<UserControl x:Class="Ns.Gui.pnlDebtor"
             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="230" d:DesignWidth="460" xmlns:my="clr-namespace:Ns.Gui">
    <Grid>
        <GroupBox Header="Debtor" HorizontalAlignment="Stretch" Margin="0,0,0,0" Name="groupBox1" VerticalAlignment="Stretch">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="28" />
                    <RowDefinition Height="56" />
                    <RowDefinition Height="28" />
                    <RowDefinition />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="80*" />
                    <ColumnDefinition Width="380*" />
                </Grid.ColumnDefinitions>
                <Label Content="Name:" Height="28" HorizontalAlignment="Left" Name="lblName" VerticalAlignment="Top" />
                <Label Content="Address:" Grid.Row="1" Height="28" HorizontalAlignment="Left" Name="lblAddress" VerticalAlignment="Top" />
                <Label Content="Customer Nr.:" Grid.Row="2" Height="28" HorizontalAlignment="Left" Name="lblCustomerNr" VerticalAlignment="Top" />
                <TextBox Grid.Column="1" Height="23" HorizontalAlignment="Stretch" Margin="0,0,0,0" Name="tbName" VerticalAlignment="Top" IsEnabled="False" IsReadOnly="False" Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=my:pnlDebtor, AncestorLevel=1}, Path=DebtorName, Mode=OneWay}" />
                <TextBox Grid.Column="1" Grid.Row="1" Height="46" HorizontalAlignment="Stretch" Margin="0,0,0,0" Name="tbAddress" VerticalAlignment="Top" IsReadOnly="True" IsEnabled="False" Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=my:pnlDebtor, AncestorLevel=1}, Path=Adresse, Mode=OneWay}" />
                <TextBox Grid.Column="1" Grid.Row="2" Height="23" HorizontalAlignment="Stretch" Margin="0,0,0,0" Name="tbCustomerNr" VerticalAlignment="Top" IsEnabled="False" IsReadOnly="True" />
                <Button Content="Debtor Details" Grid.ColumnSpan="2" Grid.Row="3" Height="23" HorizontalAlignment="Left" Margin="0,0,0,0" Name="btnDetails" VerticalAlignment="Top" />
            </Grid>
        </GroupBox>
    </Grid>
</UserControl>

我的姓名和地址文本框绑定到pnlDebtor UserControl的DebtorName和DebtorAddress属性。

Codebehind就像这样:

public partial class pnlDebtor : UserControl
{
    private MyFile file = null;
    public MyFile File
    {
        get
        {
            return file;
        }

        set
        {
            file = value;
            tbCustomerNr.Text = file.CustomerNo;
        }
    }

    private Contact debtor = null;
    public Contact Debtor
    {
        get
        {
            if (debtor == null)
            {
                if (File != null)
                {
                    debtor = AbstractDataObject.GetObject4ID<Contact>(File.DebtorID);
                }
            }

            return debtor;
        }
    }

    private Address debtorAddress = null;
    public string Address
    {
        get
        {
            string result = string.Empty;

            if (debtorAddress == null)
            {
                if (Debtor != null)
                {
                    List<Address> lsAddresses = AbstractDataObject.GetObject4NonIdProperty<Address>("ContactID", Debtor.ID);

                    if (lsAddresses.Any())
                    {
                        debtorAddress = lsAddresses[0];

                        result += lsAddresses[0].Street + "\r\n"
                            + lsAddresses[0].PostalCode + " " + lsAddresses[0].City;
                    }
                }
            }
            else
            {
                result += debtorAddress.Street + "\r\n"
                    + debtorAddress.PostalCode + " " + debtorAddress.City;
            }

            return result;
        }
    }

    private string strDebtorName = string.Empty;
    public string DebtorName
    {
        get
        {
            if (strDebtorName== string.Empty)
            {
                if (Debtor != null)
                {
                    strDebtorName = Debtor.Name1;

                    if (Debtor.FirstName != null)
                        strSchuldnerName += ", " + Debtor.FirstName;
                }
            }

            return strDebtorName;
        }
    }

    public pnlDebtor()
    {
        InitializeComponent();
    }
}

如您所见,与名称和地址文本框不同,我的CustomerNr文本框填充在代码隐藏中。当我传入我的文件对象时,我提取客户编号并将该值分配给相应文本框的Text属性。两种方法都有效,但第一种方法(Binding)似乎更适合WPF。为什么呢?

对我来说,缺点是: 1)逻辑和表示没有分开。如果我将我的xaml发送给设计中的某个人,他们就有可能搞砸我的绑定。 2)如果我正在调试并设置断点,则绑定的Textboxes的Text属性始终为空字符串。我看不出发生了什么。

那么,使用绑定有什么好处?为什么它是首选方法?用小字。这是我的第一个WPF项目。 :)

1 个答案:

答案 0 :(得分:2)

我认为这里缺少的链接是MVVM。您对代码隐藏中的属性的绑定意味着该特定UserControl仍然紧密耦合到该特定类。我不会说它比没有绑定的版本更好。除非XAML页面与它捆绑在一起,否则代码隐藏类不会编译,因为它引用了tbCustomerNr.Text

使用MVVM和绑定,ViewModel 与View完全隔离。如果我愿意,我可以完全从我的程序中删除视图,ViewModels仍然可以编译而不会有任何抱怨。这意味着可以轻松地重用ViewModel逻辑,并且可以干净地分离逻辑和UI开发任务。