wpf editable ListView
I am trying to make a field in ListView editable. I mean when I select row in listView one field becomes textbox instead of textblock. But it doesnt work - I see both controls all the time.
xaml:
<Window x:Class="fastnn_speedTest.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:local="clr-namespace:fastnn_speedTest"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Title="fastnn: not saved" Height="300" Width="300">
<Window.Resources>
<local:BoolToVisibilityConverter x:Key="VisibilityOfBool" />
<local:StringToIntValueConverter x:Key="StringToInt" />
<local:StringToFloatValueConverter x:Key="StringToFloat" />
<ObjectDataProvider MethodName="GetValues" ObjectType="{x:Type sys:Enum}" x:Key="ActivationEnum">
<ObjectDataProvider.MethodParameters>
<x:Type x:TypeName="local:Network+Layer+ActivFunction" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
<ObjectDataProvider MethodName="GetValues" ObjectType="{x:Type sys:Enum}" x:Key="ComputeMethodEnum">
<ObjectDataProvider.MethodParameters>
<x:Type x:TypeName="local:Training+ComputeMethodEnum" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
<Style TargetType="{x:Type TextBlock}" x:Key="ListTextBlockStyle">
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Visibility" Value="{Binding Path=IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListViewItem}}, Converter={StaticResource VisibilityOfBool}, ConverterParameter=True}" />
</Style>
<Style TargetType="{x:Type FrameworkElement}" x:Key="ListTextBoxStyle">
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Visibility" Value="{Binding Path=IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListViewItem}}, Converter={StaticResource VisibilityOfBool}, ConverterParameter=False}" />
</Style>
<DataTemplate x:Key="ActivationTemplate">
<ComboBox ItemsSource="{Binding Source={StaticResource ActivationEnum}}" SelectedValue="{Binding Path=Activation}" Width="100"/>
</DataTemplate>
<DataTemplate x:Key="NeuronsTemplate">
<Grid>
<TextBox Text="{Binding Path=Neurons}" Width="40" Style="{Binding Source=StaticResource ListTextBoxStyle }"></TextBox>
<TextBlock Text="{Binding Path=Neurons}" Width="40" Style="{Binding Source=StaticResource ListTextBlockStyle }"></TextBlock>
</Grid>
</DataTemplate>
</Window.Resources>
<Grid Background="LightGray">
<Grid.RowDefinitions>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="auto"></RowDefinition>
</Grid.RowDefinitions>
<Menu Grid.Row="0">
<MenuItem Header="File">
<MenuItem Header="New" Click="MenuNew_Click"></MenuItem>
<MenuItem Header="Open" Click="MenuOpen_Click"></MenuItem>
<Separator></Separator>
<MenuItem Header="Save" Click="MenuSave_Click"></MenuItem>
<MenuItem Header="Save As" Click="MenuSaveAs_Click"></MenuItem>
<Separator></Separator>
<MenuItem Header="Exit"></MenuItem>
</MenuItem>
</Menu>
<TabControl Grid.Row="1" Name="Tabs">
<TabItem Header="Network">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="auto"></RowDefinition>
</Grid.RowDefinitions>
<ListView Grid.Row="0" x:Name="NetworkListview" ItemsSource="{Binding network.Layers}" IsSynchronizedWithCurrentItem="True">
<ListView.View>
<GridView>
<GridViewColumn Width="100" Header="layer name" DisplayMemberBinding="{Binding Name}"/>
<GridViewColumn Width="60" Header="neurons" CellTemplate="{StaticResource NeuronsTemplate}"/>
<GridViewColumn Width="110" Header="activation" CellTemplate="{StaticResource ActivationTemplate}"/>
</GridView>
</ListView.View>
</ListView>
<UniformGrid Grid.Row="1" Rows="1">
<Button Name="AddLayerButton" Click="AddLayerButton_Click">Add layer</Button>
<Button Name="RemoveLayerButton" Click="RemoveLayerButton_Click">Remove layer</Button>
</UniformGrid>
</Grid>
</TabItem>
<TabItem Header="Data set">
<UniformGrid Columns="2" Height="70" Width="220">
<Label>input dimmension</Label>
<TextBox Text="{Binding Path=data_set.InputDimmension, Mode=TwoWay, Converter={StaticResource StringToInt}}"></TextBox>
<Label>output dimmension</Label>
<TextBox Text="{Binding Path=data_set.OutputDimmension, Mode=TwoWay, Converter={StaticResource StringToInt}}"></TextBox>
<Label>number of samples</Label>
<TextBox Text="{Binding Path=data_set.SamplesNumber, Mode=TwoWay}"></TextBox>
</UniformGrid>
</TabItem>
<TabItem Header="Training">
<UniformGrid Columns="2" Width="230" Height="170">
<Label>learning rate</Label>
<TextBox Text="{Binding Path=training.LearningRate, Mode=TwoWay, Converter={StaticResource StringToFloat}}"></TextBox>
<Label>epochs</Label>
<TextBox Text="{Binding Path=training.Epochs, Mode=TwoWay, Converter={StaticResource StringToInt}}"></TextBox>
<Label>weights stddev</Label>
<TextBox Text="{Binding Path=training.WeightsStddev, Mode=TwoWay, Converter={StaticResource StringToFloat}}"></TextBox>
<Label>srand(0)</Label>
<CheckBox Margin="0,4,0,0" IsChecked="{Binding Path=training.SrandZero}"></CheckBox>
<Label>compute method</Label>
<ComboBox Name="ComputeMethodCombo" ItemsSource="{Binding Source={StaticResource ComputeMethodEnum}}" SelectedValue="{Binding Path=training.ComputeMethod}"></ComboBox>
<Label>select device</Label>
<ComboBox Name="DeviceComboBox" SelectedIndex="{Binding Path=training.DeviceIndex}"></ComboBox>
<Label>click to run test</Label>
<Button Margin="2" Name="RunTestButton" Click="RunTestButton_Click">Run test</Button>
</UniformGrid>
</TabItem>
<TabItem Header="Output">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="auto"></RowDefinition>
</Grid.RowDefinitions>
<TextBox Grid.Row="0" Name="LogTextBox"></TextBox>
<UniformGrid Grid.Row="1" Rows="1">
<Button>Save</Button>
<Button Name="ClearButton" Click="ClearButton_Click">Clear</Button>
<Button>Eerror chart</Button>
<Button>Speed chart</Button>
</UniformGrid>
</Grid>
</TabItem>
</TabControl>
<StatusBar Grid.Row="2">
<StatusBarItem>
<TextBlock>text</TextBlock>
</StatusBarItem>
</StatusBar>
</Grid>
converter:
public class BoolToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType,
object parameter, System.Globalization.CultureInfo culture)
{
bool param = bool.Parse(parameter as string);
bool val = (bool)value;
return val == param ? Visibility.Visible : Visibility.Hidden;
}
public object ConvertBack(object value, Type targetType,
object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
and a Network class which contains ObservableCollection which is bound to listview:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using System.Xml.Serialization;
namespace fastnn_speedTest
{
public c开发者_运维知识库lass Network
{
public class Layer : INotifyPropertyChanged
{
public enum ActivFunction { LINEAR, EXPONENTIAL, ARCUSTANGENT }
private string name;
[XmlIgnore]
public string Name
{
get
{
return name;
}
set
{
name = value;
RaisePropertyChanged("Name");
}
}
[XmlAttribute]
public ActivFunction Activation { get; set; }
[XmlAttribute]
public int Neurons { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void RaisePropertyChanged(String propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
public ObservableCollection<Layer> Layers { get; set; }
public Network()
{
Layers = new ObservableCollection<Layer>();
}
public void AddLayer(Layer layer)
{
int last = Layers.Count;
if (last > 0)
{
Layers.Last().Name = "Layer " + last + " (hidden)";
}
layer.Name = "Layer " + (last + 1) + " (output)";
Layers.Add(layer);
}
public void RemoveLayer(int index)
{
if( index >= 0 && index < Layers.Count )
Layers.RemoveAt(index);
}
public void Clear()
{
Layers.Clear();
}
public void Validate()
{
if (Layers.Count < 1)
throw new ArgumentException("minimum number of layers is 1");
foreach (Layer layer in Layers)
{
if (layer.Neurons <= 0)
throw new ArgumentException("neurons in each layer must be > 0");
}
if(Layers.Last().Activation != Layer.ActivFunction.LINEAR)
throw new ArgumentException("last layer must be linear");
}
}
}
Have a look at the below links
http://www.switchonthecode.com/tutorials/wpf-tutorial-using-the-listview-part-3-in-place-edit
EDIT
You may have followed the tut but couple of things you missed is what causing the probs.First of all you are trying to use the inbuilt BooleanToVisibility converter but i think in your scenario its not gonna help.You have to crate a custom value converter like mentioned in the tutorial.
public class BoolToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType,
object parameter, System.Globalization.CultureInfo culture)
{
bool param = bool.Parse(parameter as string);
bool val = (bool)value;
return val == param ? Visibility.Visible : Visibility.Hidden;
}
public object ConvertBack(object value, Type targetType,
object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
Also you have to mention your converter like this
<Setter Property="Visibility" Value="{Binding Path=IsSelected,
RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type ListViewItem}},
Converter={StaticResource VisibilityOfBool}, ConverterParameter=False}" />
Make these changes and you are good to go....
Why don't you use the data grid? You can style it to look like a list and it already provides the edit mode functionality. You can use a TemplateColumn to provide custom display and editing views.
精彩评论