【问题标题】:Caliburn Micro, Binding and NotifyingCaliburn Micro,绑定和通知
【发布时间】:2012-10-12 06:16:18
【问题描述】:

经过几个月的 WPF 实践后,我决定试一试 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 中的属性应该绑定到视图中同名的元素。

  • 首先,请注意PlayerList 只是我创建的PlayerProfiles 中玩家名称的列表,因为当绑定到Combobox 时,当我命名为Combobox PlayerProfiles,但是当我通过列表并将其命名为PlayerList 时它们会这样做——尽管我已经覆盖了PlayerProfile class 中的ToString 方法。为什么?这看起来很笨拙...(如果您想知道的话,staticInfos.Load() 方法会使用几个虚拟名称填充PlayerProfiles...)

  • 1234563组合框 1234563为什么?

对于这些基本问题,我很抱歉,我已经盯着“Hello World”caliburn 示例看了好几个小时,但没有看到我遗漏了什么……谢谢。提前!

编辑:这是 .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>

【问题讨论】:

  • 能否请您也发布您的MainView XAML?

标签: wpf binding caliburn.micro


【解决方案1】:

首先,我将首先删除您的 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;

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

【讨论】:

  • 感谢您的回答!但是,当我直接绑定到“PlayerProfiles”时(并且我在通知中进行了更改),Combobox 不显示名称,而是显示了两次(Load() 方法生成了两个配置文件)条目“找不到视图” Project_MVVM.Models.PlayerProfile'。这是什么意思?
  • 另外,为了确定,我认为如果我写 'string a...' 和 'private string a... ',它们的编译方式完全相同,即省略前缀自动将其设置为私有,还是我错了?
  • 您是对的,但最好是明确并添加“私人”访问修饰符。就您的第一个问题而言,默认情况下,Caliburn.Micro 将假定您的集合中的类型是视图模型,并会尝试找到与之关联的视图(例如 PlayerProfile.xaml),并且它将绑定您的 PlayerProfile 类型到 PlayerProfile 视图)。但是,由于这不是视图模型类型,您可以将 ComboBox 的“DisplayMemberPath”属性设置为您的 PlayerProfile 类型的属性,或者创建一个 ComboBox ItemTemplate。
  • 查看 stackoverflow.com/questions/883626/… 以获取 ItemTemplate 的示例。如果您想在 ComboBox 中显示多个字符串,则可以使用它。
  • 所以Caliburn在显示对象时默认不使用ToString方法,很高兴知道!我想除了模板,我还可以创建一个新的 .xaml '包含该模板',但作为 PlayerProfile 模型的视图?
【解决方案2】:

我想我得到了答案

在您的文本框中使用 updatesourcetrigger=property changed Can Execute 没有更新,因为您没有使用依赖(或依赖项不记得名称)属性。

组合框未更新,因为您应该将其绑定到可绑定集合。

【讨论】:

  • 对于所有文本框实例,更新源触发器默认设置为使用 Caliburn.Micro 更改的属性。
  • 不过,我还没有让那部分工作。现在按下按钮时,我正在向组合框添加一个新播放器,但是无论文本框的内容是什么,播放器都没有名称(即组合框选项中出现了一条白线)...为什么?
  • 任何人有一个想法,文本框绑定仍然无法正常工作 :-( ... 一切仍如上次评论。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多