我有一个编辑器(文本框),我想根据点击的按钮将不同的文本绑定到它。
我可以在按钮上使用命令并通过命令参数传递我想编辑的字符串,并更新绑定到文本框的字符串。这将有效,但它不会保存修改,因为文本(通过命令参数传递)和文本框的文本之间没有绑定。
我的问题是,如果不直接从View模型访问文本框,我应该如何巧妙地实现此绑定?
编辑:我想要达到的目标可能很模糊。我试着澄清一点:
所以,假设我有几个不同的按钮,如果我点击其中一个,它应该将一些字符串绑定到编辑器的文本框,我可以在其中修改它并稍后保存。
<Button Content="Edit query" Command="{Binding ShowQueryInEditorCommand}" CommandParameter="{Binding SomeSqlStringToBeEdited}"/>
<Button Content="Edit query" Command="{Binding ShowQueryInEditorCommand}" CommandParameter="{Binding SomeOtherSqlStringToBeEdited}"/>
这是命令将执行的内容:
public void ShowQueryInEditor(object o)
{
string SqlStatementParam = o as string;
if (SqlStatementParam != null)
SQLStatement = SqlStatementParam;
}
编辑器TextBox本身:
<TextBox Text="{Binding SQLStatement}">
正如您所看到的,这是非常基本的,因为它只是设置SQLStatement字符串,但它们之间没有绑定,因此它无法将修改反映回SomeSqlStringToBeEdited / SomeOtherSqlStringToBeEdited。这就是我想要实现的,在单击按钮时以某种方式将该字符串绑定到文本框。
答案 0 :(得分:2)
我可以想到两种基本方式:通过代码,或通过Xaml。
在代码中,不是从ViewModel访问文本框,而是在ViewModel中为“DisplayText”或“SelectedText”添加一个新属性,或者在您的场景中添加任何有意义的属性。将文本框绑定到该属性,然后将所需的其余逻辑放在setter中(或者,如果它是DependencyProperty
,则为OnPropertyChanged
回调)。这保留了ViewModel中的所有逻辑,意味着Xaml不必关心。
或者在Xaml中,您可以使用触发器和模板根据所选按钮更改文本框。最有可能形成您的描述,我建议使用多个文本框,一个绑定到每个字符串,并根据单击的按钮切换可见文本框。这使ViewModel无法忽略此特定于显示的逻辑,并允许您稍后更轻松地更改它。
就个人而言,我可能会建议使用Xaml方法,但这取决于您的具体情况。
答案 1 :(得分:0)
根据
但问题是按钮是动态创建的
1)将查询文本和按钮包装到视图模型中,如下所示:
public class ViewModel : ViewModelBase
{
public ViewModel()
{
this.turnIsSelectedOnCommand = new RelayCommand(() => IsSelected = true);
}
public String Text
{
get { return text; }
set
{
if (text != value)
{
text = value;
OnPropertyChanged("Text");
}
}
}
private String text;
public Boolean IsSelected
{
get { return isSelected; }
set
{
if (isSelected != value)
{
isSelected = value;
OnPropertyChanged("IsSelected");
}
}
}
private Boolean isSelected;
public RelayCommand TurnIsSelectedOnCommand
{
get { return turnIsSelectedOnCommand; }
}
private readonly RelayCommand turnIsSelectedOnCommand;
}
2)将动态创建的文本/按钮放入集合中。为简单起见,我已将它们添加到数组中:
public MainWindow()
{
InitializeComponent();
DataContext = new[]
{
new ViewModel { Text = "SELECT * FROM Foo", IsSelected = true },
new ViewModel { Text = "SELECT * FROM Bar" },
new ViewModel { Text = "DROP TABLE Foo" },
new ViewModel { Text = "DROP TABLE Bar" },
};
}
3)使用ListBox和编辑器绑定集合 - 使用所选项目的Text
:
<ListBox Grid.Row="0" Margin="5" ItemsSource="{Binding}" x:Name="lbItems">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"
VerticalAlignment="Center"
HorizontalAlignment="Right"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="IsSelected" Value="{Binding IsSelected}"/>
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}"
Color="Transparent"/>
</Style.Resources>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<Button Content="Edit query" Command="{Binding TurnIsSelectedOnCommand}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<TextBox Grid.Row="1" Margin="5" Text="{Binding Path=SelectedItem.Text, ElementName=lbItems}" />
我添加了一些样式修改。 首先修改按钮布局。 第二个意思是,当您按下按钮并且ViewModel将被选中时,也将选择列表框项目。 第三个从所选项目的背景中隐藏选择。
希望,这有帮助。