将对象绑定到组合框和文本框
Bind object to combobox and textbox
我有以下型号:
public class Tag : ObservableObject
{
private int _id = -1;
public int Id
{
get { return _id; }
set
{
if (value != _id)
{
_id = value;
OnPropertyChanged("Id");
}
}
}
private string _name;
public string Name
{
get { return _name; }
set
{
if (value != _name)
{
_name = value;
OnPropertyChanged("Name");
}
}
}
private string _freeText;
public string FreeText
{
get { return _freeText; }
set
{
if (value != _freeText)
{
_freeText = value;
OnPropertyChanged("FreeText");
}
}
}
}
public class Item : ObservableObject
{
// ...
private Tag _tag;
public Tag Tag
{
get { return _tag; }
set
{
if (value != _tag)
{
_tag= value;
OnPropertyChanged("Tag");
}
}
}
}
以下视图模型:
public class AppViewModel : ViewModelBase
{
private Item _item;
public Item Item
{
get { return _item; }
set
{
if (_item != value)
{
_item = value;
OnPropertyChanged("Item");
}
}
}
private List<Tag> _tags;
public List<Tag> Tags
{
get { return _tags; }
set
{
if (_tags != value)
{
_tags = value;
OnPropertyChanged("Tags");
}
}
}
//...
}
我的标签列表中填充了以下数据:
Tags = new List<Tag>()
{
new Tag()
{
Id = 0,
Name = "Free Text"
},
new Tag()
{
Id = 1,
Name = "Tag 1"
},
new Tag()
{
Id = 2,
Name = "Tag 2"
},
new Tag()
{
Id = 3,
Name = "Tag 3"
}
}
以及以下视图:
<ComboBox x:Name="cmbTags"
ItemsSource="{Binding Tags}"
DisplayMemberPath="Name"
SelectedItem="{Binding Item.Tag}"/>
<TextBox x:Name="txtTagFreeText" Text="{Binding ElementName=cmbTags, Path=SelectedItem.FreeText}">
<TextBox.Style>
<Style TargetType="TextBox">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=cmbTags, Path=SelectedItem.Id}" Value="0">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
我想要做的是将 ComboBox Items Source 绑定到我的 Tags 列表,并将 SelectedItem 绑定到我的 Item。我设法设置了它。
然后,如果选择了Id为0的Tag,我要显示TextBox,那也设置好了。
我遇到的问题是将 TextBox 的文本与我的 Item.Tag.
的 属性 FreeText 绑定
绑定有点用,但它被应用到我的所有项目,所以每当我更改我的项目时,文本框将始终显示我最后的输入。
我还尝试将 TextBox 文本绑定更改为:
{Binding Item.Tag.FreeText}
但是我也有同样的问题。
有人知道我做错了什么吗?
我需要 post 更多代码吗?
感谢任何帮助或反馈。
谢谢。
您正在绑定到一个空实例 AppViewModel 的项目 属性 应该用一个实例初始化,但这不会解决您应该将 ComboBox 与另一个 属性 绑定的问题ViewModel 让它在 setter 中命名为 SelectedTag,处理你想要的逻辑。
public class AppViewModel : ObservableObject
{
private Item _item = new Item();
public Item Item
{
get { return _item; }
set
{
if (_item != value)
{
_item = value;
OnPropertyChanged("Item");
}
}
}
private Tag _SelectedTag;
public Tag SelectedTag
{
get { return _SelectedTag; }
set
{
if (_SelectedTag != value)
{
_SelectedTag = value;
OnPropertyChanged("SelectedTag");
Item.Tag = _SelectedTag;
if (_SelectedTag.Id == 0)
{
_SelectedTag.FreeText = "";
}
}
}
}
private List<Tag> _tags;
public List<Tag> Tags
{
get { return _tags; }
set
{
if (_tags != value)
{
_tags = value;
OnPropertyChanged("Tags");
}
}
}
// ...
}
和XAML代码:
<ComboBox x:Name="cmbTags"
ItemsSource="{Binding Tags}"
DisplayMemberPath="Name"
SelectedItem="{Binding SelectedTag,Mode=TwoWay}"/>
<TextBox Text="{Binding SelectedTag.FreeText,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}">
<TextBox.Style>
<Style TargetType="TextBox">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding SelectedTag.Id}" Value="0">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
更新
另一种方法可以直接绑定,方法是在标签更改时监听项目 属性Changed 事件 Raise Tag 属性 在 AppViewModel 上你是否合乎逻辑。
public class AppViewModel : ObservableObject
{
private Item _item;
public Item Item
{
get { return _item; }
set
{
if (_item != value)
{
_item = value;
_item.PropertyChanged -= _item_PropertyChanged;
_item.PropertyChanged += _item_PropertyChanged;
OnPropertyChanged("Item");
}
}
}
private List<Tag> _tags;
public List<Tag> Tags
{
get { return _tags; }
set
{
if (_tags != value)
{
_tags = value;
OnPropertyChanged("Tags");
}
}
}
public AppViewModel()
{
Item = new Item();
Tags = new List<Tag>()
{
new Tag()
{
Id = 0,
Name = "Free Text"
},
new Tag()
{
Id = 1,
Name = "Tag 1"
},
new Tag()
{
Id = 2,
Name = "Tag 2"
},
new Tag()
{
Id = 3,
Name = "Tag 3"
}
};
}
private void _item_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(Item.Tag))
{
if (Item.Tag.Id == 0)
{
Item.Tag.FreeText = string.Empty;
}
OnPropertyChanged(nameof(Item));
}
}
}
并直接绑定ComboBox和Item Tag
<TextBox x:Name="txtTagFreeText" Text="{Binding Item.Tag.FreeText,Mode=TwoWay}">
<TextBox.Style>
<Style TargetType="TextBox">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding Item.Tag.Id}" Value="0">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
我有以下型号:
public class Tag : ObservableObject
{
private int _id = -1;
public int Id
{
get { return _id; }
set
{
if (value != _id)
{
_id = value;
OnPropertyChanged("Id");
}
}
}
private string _name;
public string Name
{
get { return _name; }
set
{
if (value != _name)
{
_name = value;
OnPropertyChanged("Name");
}
}
}
private string _freeText;
public string FreeText
{
get { return _freeText; }
set
{
if (value != _freeText)
{
_freeText = value;
OnPropertyChanged("FreeText");
}
}
}
}
public class Item : ObservableObject
{
// ...
private Tag _tag;
public Tag Tag
{
get { return _tag; }
set
{
if (value != _tag)
{
_tag= value;
OnPropertyChanged("Tag");
}
}
}
}
以下视图模型:
public class AppViewModel : ViewModelBase
{
private Item _item;
public Item Item
{
get { return _item; }
set
{
if (_item != value)
{
_item = value;
OnPropertyChanged("Item");
}
}
}
private List<Tag> _tags;
public List<Tag> Tags
{
get { return _tags; }
set
{
if (_tags != value)
{
_tags = value;
OnPropertyChanged("Tags");
}
}
}
//...
}
我的标签列表中填充了以下数据:
Tags = new List<Tag>()
{
new Tag()
{
Id = 0,
Name = "Free Text"
},
new Tag()
{
Id = 1,
Name = "Tag 1"
},
new Tag()
{
Id = 2,
Name = "Tag 2"
},
new Tag()
{
Id = 3,
Name = "Tag 3"
}
}
以及以下视图:
<ComboBox x:Name="cmbTags"
ItemsSource="{Binding Tags}"
DisplayMemberPath="Name"
SelectedItem="{Binding Item.Tag}"/>
<TextBox x:Name="txtTagFreeText" Text="{Binding ElementName=cmbTags, Path=SelectedItem.FreeText}">
<TextBox.Style>
<Style TargetType="TextBox">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=cmbTags, Path=SelectedItem.Id}" Value="0">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
我想要做的是将 ComboBox Items Source 绑定到我的 Tags 列表,并将 SelectedItem 绑定到我的 Item。我设法设置了它。
然后,如果选择了Id为0的Tag,我要显示TextBox,那也设置好了。
我遇到的问题是将 TextBox 的文本与我的 Item.Tag.
的 属性 FreeText 绑定绑定有点用,但它被应用到我的所有项目,所以每当我更改我的项目时,文本框将始终显示我最后的输入。
我还尝试将 TextBox 文本绑定更改为:
{Binding Item.Tag.FreeText}
但是我也有同样的问题。
有人知道我做错了什么吗? 我需要 post 更多代码吗?
感谢任何帮助或反馈。
谢谢。
您正在绑定到一个空实例 AppViewModel 的项目 属性 应该用一个实例初始化,但这不会解决您应该将 ComboBox 与另一个 属性 绑定的问题ViewModel 让它在 setter 中命名为 SelectedTag,处理你想要的逻辑。
public class AppViewModel : ObservableObject
{
private Item _item = new Item();
public Item Item
{
get { return _item; }
set
{
if (_item != value)
{
_item = value;
OnPropertyChanged("Item");
}
}
}
private Tag _SelectedTag;
public Tag SelectedTag
{
get { return _SelectedTag; }
set
{
if (_SelectedTag != value)
{
_SelectedTag = value;
OnPropertyChanged("SelectedTag");
Item.Tag = _SelectedTag;
if (_SelectedTag.Id == 0)
{
_SelectedTag.FreeText = "";
}
}
}
}
private List<Tag> _tags;
public List<Tag> Tags
{
get { return _tags; }
set
{
if (_tags != value)
{
_tags = value;
OnPropertyChanged("Tags");
}
}
}
// ...
}
和XAML代码:
<ComboBox x:Name="cmbTags"
ItemsSource="{Binding Tags}"
DisplayMemberPath="Name"
SelectedItem="{Binding SelectedTag,Mode=TwoWay}"/>
<TextBox Text="{Binding SelectedTag.FreeText,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}">
<TextBox.Style>
<Style TargetType="TextBox">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding SelectedTag.Id}" Value="0">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
更新
另一种方法可以直接绑定,方法是在标签更改时监听项目 属性Changed 事件 Raise Tag 属性 在 AppViewModel 上你是否合乎逻辑。
public class AppViewModel : ObservableObject
{
private Item _item;
public Item Item
{
get { return _item; }
set
{
if (_item != value)
{
_item = value;
_item.PropertyChanged -= _item_PropertyChanged;
_item.PropertyChanged += _item_PropertyChanged;
OnPropertyChanged("Item");
}
}
}
private List<Tag> _tags;
public List<Tag> Tags
{
get { return _tags; }
set
{
if (_tags != value)
{
_tags = value;
OnPropertyChanged("Tags");
}
}
}
public AppViewModel()
{
Item = new Item();
Tags = new List<Tag>()
{
new Tag()
{
Id = 0,
Name = "Free Text"
},
new Tag()
{
Id = 1,
Name = "Tag 1"
},
new Tag()
{
Id = 2,
Name = "Tag 2"
},
new Tag()
{
Id = 3,
Name = "Tag 3"
}
};
}
private void _item_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(Item.Tag))
{
if (Item.Tag.Id == 0)
{
Item.Tag.FreeText = string.Empty;
}
OnPropertyChanged(nameof(Item));
}
}
}
并直接绑定ComboBox和Item Tag
<TextBox x:Name="txtTagFreeText" Text="{Binding Item.Tag.FreeText,Mode=TwoWay}">
<TextBox.Style>
<Style TargetType="TextBox">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding Item.Tag.Id}" Value="0">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>