Caliburn Micro,绑定和通知

时间:2012-10-22 12:23:21

标签: wpf binding caliburn.micro

经过几个月的实际操作,我决定给Caliburn Micro一个机会。我有几件事无法上班。我会先发布代码,看看下面的问题/问题:

public class MainViewModel : PropertyChangedBase
{
    BindableCollection<PlayerProfile> _playerProfiles = staticInfos.Load();

    public BindableCollection<PlayerProfile> PlayerProfiles {
        get { return _playerProfiles; }
        set { 
            _playerProfiles = value;
            NotifyOfPropertyChange(() => PlayerList);
        }
    }

    string _tb_AddPlayer;
    public string TB_AddPlayer {
        get { return _tb_AddPlayer; }
        set { 
            _tb_AddPlayer = value;
            NotifyOfPropertyChange(() => TB_AddPlayer);
            NotifyOfPropertyChange(() => CanAddPlayer);
        }
    }

    List<string> _pl = new List<string>(); 
    public List<string> PlayerList {
        get{
            foreach (PlayerProfile p in PlayerProfiles) {
                if (!_pl.Contains(p.Name)) _pl.Add(p.Name);
            }
            return _pl;               
        }
        set {
            _pl = value;
            NotifyOfPropertyChange(()=>PlayerList);
        }
    }

    // Dummy Test String
    string _test;
    public string Test { 
        get { return _test; } 
        set { 
            _test = value; 
            NotifyOfPropertyChange(() => Test); 
        }
    }

    // Button Action
    public void AddPlayer() {
         _playerProfiles.Add(new PlayerProfile(TB_AddPlayer));
         Test = "Pressed";
         NotifyOfPropertyChange(() => PlayerProfiles);
    }

    public bool CanAddPlayer {
        get { return true; }
        // doesnt work: get { return !string.IsNullOrWhiteSpace(TB_AddPlayer); }
    }
}

所以这里是:我使用绑定约定,即MainView中的Property应绑定到View中相同Name的Element。

  • 首先,请注意PlayerList只是PlayerProfiles中玩家姓名的列表,我创建的是因为绑定到Combobox时他们不知道当我为Combobox PlayerProfiles命名时,它会显示,但当我通过列表并将其命名为PlayerList时,它们会显示 - 虽然我已覆盖ToString中的PlayerProfile class方法。为什么?这看起来很笨拙......(staticInfos.Load()方法填充PlayerProfiles有几个虚拟名称,如果你想知道......)

  • 当我在文本框中输入内容(名为TB_AddPlayer)并按下按钮(名为AddPlayer)时,会出现测试字符串,因此我知道操作发生了,但新名称没有出现在组合框中

  • 此外,如果我使用CanAddPlayer属性中的注释行,则永远不会启用该按钮,如果我开始键入,则不会启用,也不会在文本框失去文本焦点的情况下启用。为什么呢?

对不起这些基本问题,我已经盯着'Hello World'校准示例几个小时,看不到我错过了什么... Thx。提前!

编辑:这是.xaml

<UserControl x:Class="MixGameM8_MVVM.Views.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MixGameM8_MVVM.Views">

<UserControl.Resources>
    <Style TargetType="TextBlock" x:Key="TB_A">
        <Setter Property="Margin" Value="5,5,5,5" />
        <Setter Property="HorizontalAlignment" Value="Center" />
        <Setter Property="FontSize" Value="15" />
    </Style>

    <!-- ... Some more of this kind -->
</UserControl.Resources>

<Grid>
    <!-- ... Grid definitions -->
    <Border Style="{StaticResource Border_A}" Grid.Row="0" Grid.Column="0">
        <StackPanel Name="SP_Controls">
            <TextBlock Style="{StaticResource TB_A}" Text="Controls"/>
            <ComboBox Style="{StaticResource CB_A}" Name="PlayerProfiles"/>
            <StackPanel Orientation="Horizontal">
                <TextBox Style="{StaticResource TBox_A}" Name="TB_AddPlayer" MinWidth ="100" />
                <Button Style="{StaticResource Button_AddPlayer}" Content="Add Player" Name="AddPlayer" />
             </StackPanel>
        </StackPanel>
    </Border>

<!-- ... And some more cells in the grid, one containing the dummy textbox -->

</Grid>
</UserControl>

2 个答案:

答案 0 :(得分:3)

首先,我首先删除您的PlayerList媒体资源,然后更新您的PlayerProfiles媒体资源:

 public BindableCollection<PlayerProfile> PlayerProfiles {
    get { return _playerProfiles; }
    set { 
        _playerProfiles = value;
        NotifyOfPropertyChange(() => PlayerProfiles);
    }
}

接下来,我不会将您的视图模型属性称为描述它们如何呈现的内容,即将TB_AddPlayer更改为AddPlayer(或者更好的是PlayerName,因为它就是它是)。

接下来,如果你调用你的ComboBox PlayerProfiles,那么绑定应该通过约定自动发生。在AddPlayer方法中,您希望通过属性添加新的播放器配置文件,而不是后备字段:

变化:

public void AddPlayer() {
     _playerProfiles.Add(new PlayerProfile(TB_AddPlayer));
     Test = "Pressed";
     NotifyOfPropertyChange(() => PlayerProfiles);
}

为:

public void AddPlayer() {
     this.PlayerProfiles.Add(new PlayerProfile(this.PlayerName));
}

由于PlayerProfiles是BindableCollection,因此将执行更改通知,并且您的ComboBox将会更新。

另外,我会一直为您的支持字段明确指定访问修饰符,即private string _playerName;而不仅仅是字符串_playerName;

尝试这些更改,如果仍有问题,请更新问题中的代码。

答案 1 :(得分:0)

我想我得到了答案

在文本框中使用updatesourcetrigger =属性已更改 Can Execute没有更新因为你没有使用依赖(或依赖不记住名称)属性。

组合框未更新会导致您将其绑定到可绑定的集合。