Suren97 Ответов: 2

C# как изменить имя элемента в listbox (WPF)


У меня есть текстовое поле и кнопка в левой части,мне нужно написать новое имя для выбранного элемента в списке, и после нажатия на кнопку Сохранить название моего выбранного элемента должно измениться.Что я должен написать в кнопке Save click?Это скриншот ` WPF[^]

Это мой полный код`

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = this;
    }

    public ObservableCollection<MyPicture> MyPictures { get; }
        = new ObservableCollection<MyPicture>();

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        OpenFileDialog op = new OpenFileDialog()
        {
            Title = "Select picture(s)",
            Filter = "All supported graphics|" +
                        "*.jpg;*.jpeg;*.png|" +
                        "JPEG (*.jpg;*.jpeg)|" +
                        "*.jpg;*.jpeg|" +
                        "Portable Network Graphic (*.png)" +
                        "|*.png",
            InitialDirectory = Environment.GetFolderPath(
                Environment.SpecialFolder.MyPictures),
            Multiselect = true
        };

        if (op.ShowDialog() == true)
        {
            paste(op.FileNames.Select(f => new MyPicture
            {
                Url = new Uri(f, UriKind.Absolute),
                Title = System.IO.Path.GetFileName(f)
            }));
        }
    }

    private void paste(IEnumerable<MyPicture> newPictures)
    {
        
        foreach (var item in newPictures)
        {
            MyPictures.Add(item);
        }
    }
}

public class MyPicture
{
    public Uri Url { get; set; } 
    public string Title { get; set; }
}


Что я уже пробовал:

Я уже писал так, но это не работает.

private void savebutton_Click(object sender, RoutedEventArgs e)
        {
            lb.SelectedItem= textBox.Text;
        }

2 Ответов

Рейтинг:
19

Graeme_Grant

Изменить вас Listbox.ItemTemplate следующим образом:

<ListBox.ItemTemplate>
    <DataTemplate>
        <Grid MaxWidth="200" Margin="10">
            <Grid.RowDefinitions>
                <RowDefinition/>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
            <Image Source="{Binding Url}" />
            <TextBlock MouseDown="txtblk_MouseDown" Grid.Row="1"

                        Text="{Binding Title}" />
            <TextBox LostFocus="txtbox_LostFocus"  Grid.Row="1"

                        Text="{Binding Title, Mode=TwoWay}"

                        Visibility="Collapsed" />
        </Grid>
    </DataTemplate>
</ListBox.ItemTemplate>

и добавьте следующий код к вашему коду-behind:
private void txtblk_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
    TextBox txt = (TextBox)((Grid)((TextBlock)sender).Parent).Children[2];
    txt.Visibility = Visibility.Visible;
    ((TextBlock)sender).Visibility = Visibility.Collapsed;
}

private void txtbox_LostFocus(object sender, RoutedEventArgs e)
{
    TextBlock tb = (TextBlock)((Grid)((TextBox)sender).Parent).Children[1];
    tb.Visibility = Visibility.Visible;
    ((TextBox)sender).Visibility = Visibility.Collapsed;
}

Чтобы измененные данные были отражены с помощью привязки данных, необходимо изменить MyPicture класс выглядит следующим образом:
public class MyPicture : ObservableBase
{
    public Uri Url { get; set; } // filename of image

    private string title;
    public string Title
    {
        get { return title; }
        set { Set(ref title, value); }
    }
}

и добавьте следующий класс для поддержки INotifyPropertyChanged интерфейс:
public abstract class ObservableBase : INotifyPropertyChanged
{
    public void Set<TValue>(ref TValue field, TValue newValue, [CallerMemberName] string propertyName = "")
    {
        if (EqualityComparer<TValue>.Default.Equals(field, default(TValue)) || !field.Equals(newValue))
        {
            field = newValue;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

То INotifyPropertyChanged интерфейс уведомляет систему привязки данных о том, что происходит изменение, когда PropertyChanged событие поднято. Я завернул это в базовый класс, сделав использование очень простым. Вы можете увидеть это в свойстве Title Set метод проведения MyPicture класс.

Чтобы использовать его, нажмите на текст заголовка изображения, и вы сможете его отредактировать. Как только вы нажмете вне текстового поля редактирования, изменения будут применены автоматически.


Suren97

Спасибо Вам большое :) но это просто очень трудно для меня,я хотел более простой вариант, просто написать имя в текстовом поле, а затем после нажатия на кнопку Сохранить,оно будет изменено.Но ничего,это отличная работа, Большое вам спасибо :)

Graeme_Grant

Это редактирование на месте, как и Проводник Windows... Версия Пита также будет делать то, что вы хотите.

Suren97

Привет, у меня есть новый вопрос, не могли бы вы мне помочь, пожалуйста?Это мой вопрос
C# как сохранить данные в списке, а затем добавить их в listview (WPF)[^]

Graeme_Grant

Я отправил вам ответ, однако в моем ответе нет кода. Вместо этого я дал вам две ссылки, которые лучше ответят (чем я могу в контексте этого сайта) на ваш вопрос. Они также ответят на ряд будущих вопросов, которые вы будете иметь с элементом управления ListView, те же самые, которые были у меня, когда я был и все еще использую его.

Рейтинг:
0

Pete O'Hanlon

SelectedItem возвращает объект, а не экземпляр MyPicture. Все, что вам нужно сделать, это преобразовать выбранный объект в MyPicture, а затем присвоить текст значению. Что-то вроде этого:

private void UpdateTitle()
{
  if (lb.SelectedItem == null) return;
  MyPicture picture = lb.SelectedItem as MyPicture;
  if (picture != null)
  {
    picture.Title = textBox.Text;
  }
}


Suren97

Я пробовал вот так, но ничего больше не изменилось :(

Pete O'Hanlon

Вы ставили какие-нибудь точки останова в свой код и отлаживали его, чтобы увидеть, что происходит?

Suren97

какая точка останова?

Pete O'Hanlon

В своем коде вы добавили точку останова в точке, которую вы тестируете, что SelectedItem не является нулевым, а затем перешагнули через каждую строку, чтобы увидеть, каковы эти значения? Вы ведь знаете, как отлаживать, не так ли?

Suren97

да, я добавил, Но это не меняет название выбранного элемента

Pete O'Hanlon

Вы переступали через каждую линию и проверяли, что она делает? Убедились ли вы, что преобразование SelectedItem в MyPicture действительно сработало?

О, еще одна вещь, если вы ожидаете увидеть значение обновленным обратно в пользовательском интерфейсе, вам придется вызвать событие PropertyChanged в заголовке, когда вы его измените.

Suren97

Как я могу использовать событие PropertyChanged?

Pete O'Hanlon

Серьезно? Вы занимаетесь WPF и не знаете о PropertyChanged? Ваш класс MyPicture должен реализовать INotifyPropertyChanged; это имеет событие PropertyChanged. В сеттере для вашего титула вам придется поднять событие. Поищите в интернете реализации ViewModelBase, чтобы получить представление о том, как это структурировать.

Suren97

да, я начинаю в WPF, не могли бы вы мне помочь, пожалуйста?

Graeme_Grant

Пит, это дополнительный вопрос в дополнение к первоначальному вопросу, заданному здесь: C# как загрузить изображения в список рядом друг с другом, WPF (openfiledialog)[^]