RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 615927
Accepted
Игорь Ага
Игорь Ага
Asked:2020-01-17 23:11:04 +0000 UTC2020-01-17 23:11:04 +0000 UTC 2020-01-17 23:11:04 +0000 UTC

WPF 表 XAML

  • 772

伙计们,告诉我如何通过逐页或动态数据滚动从数据库中卸载元素?任务:数据库存储学生的照片和姓名。需要显示照片,并在照片下方显示学生的姓名。

在此处输入图像描述

对于这样一个愚蠢的问题,我深表歉意,但对我来说,这仍然非常困难。也许有人可以提供一个例子。这对我来说会更容易

目前,inf。是这样拍摄的。 在此处输入图像描述

c#
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    VladD
    2020-01-18T21:46:00Z2020-01-18T21:46:00Z

    好的,好吧,让我们写下如何去做。让我们立即尝试从中创建 MVVM。

    让我们从模型开始。最主要的是,该模型应该尝试从我们这里抽象出它背后的东西。考虑到这一点,让我们将其简单地组织为内存中的模型对象列表。外部代码不应依赖于它。

    所以:

    public class StudentModel
    {
        public string Name { get; set; }
        public Uri ImageUri { get; set; }
    }
    
    public class StudentListModel
    {
        const string uri = "https://www.gravatar.com/avatar/f81585f940e68c3bab934cc6f59c901e?" +
                           "s=328&d=identicon&r=PG";
    
        public IEnumerable<StudentModel> GetAllStudents() =>
            Enumerable.Range(0, 200).Select(n =>
                new StudentModel() { Name = $"Student #{n}", ImageUri = new Uri(uri) });
    }
    

    我将“获取n第页”功能留给了 VM,请记住,实际上您IEnumerable将拥有IQueryable. 如果您想在碱基调用之上创建一个存储库(例如,因为您不使用 EF),为什么不呢。

    对于现在的模型,您必须亲自将底座插入此处。让我们继续讨论虚拟机。

    首先,VM 的基类。如果您正在使用任何 MVVM 框架,那么您已经拥有它。如果没有,我们会把它写下来。它必须实现INotifyPropertyChanged:

    class VM : INotifyPropertyChanged
    {
        protected bool Set<T>(ref T field, T value,
                              [CallerMemberName] string propertyName = null)
        {
            if (EqualityComparer<T>.Default.Equals(field, value))
                return false;
    
            field = value;
            RaisePropertyChanged(propertyName);
            return true;
        }
    
        protected void RaisePropertyChanged([CallerMemberName] string propertyName = null) =>
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    
        public event PropertyChangedEventHandler PropertyChanged;
    }
    

    现在一个班负责一个学生。这很简单:

    class StudentVM : VM
    {
        string name;
        public string Name { get { return name; } set { Set(ref name, value); } }
    
        Uri imageUri;
        public Uri ImageUri { get { return imageUri; } set { Set(ref imageUri, value); } }
    
        public StudentVM(string name, Uri uri) { this.name = name; this.imageUri = uri; }
    }
    

    如果你顺势而为,而且你有不可变的类,那就更容易了:

    class StudentVM : VM
    {
        public string Name { get; }
        public Uri ImageUri { get; }
    
        public StudentVM(string name, Uri uri) { this.Name = name; this.ImageUri = uri; }
    }
    

    接下来是处理学生名单的课程。我们会一段一段地写出来。开始吧。

    class StudentListVM : VM
    {
    

    我们需要一个负责页数的属性。没有他什么都没有。我们写:

        int totalPages;
        public int TotalPages
        {
            get { return totalPages; }
            private set
            {
                if (value < 0)
                    throw new ArgumentException(nameof(TotalPages));
                Set(ref totalPages, value);
            }
        }
    

    虽然一切都很简单。是的,如果我们没有一个学生,我们可能想在 UI 中显示一些特别的东西,所以我们放了一个辅助属性:

        bool havePages;
        public bool HavePages
        {
            get { return havePages; }
            private set { Set(ref havePages, value); }
        }
    

    并且不要忘记在设置器中设置它TotalPages:

            private set
            {
                if (value < 0)
                    throw new ArgumentException(nameof(TotalPages));
                Set(ref totalPages, value);
                HavePages = totalPages > 0; // <--- добавили
            }
    

    下一项是当前页码。他的一切都一样,只是二传手的检查更多了。

        int currentPageNo;
        public int CurrentPageNo
        {
            get { return currentPageNo; }
            set
            {
                if (value < 0)
                    throw new ArgumentException(nameof(CurrentPageNo));
                if (value >= TotalPages && HavePages)
                    throw new ArgumentException(nameof(CurrentPageNo));
                if (value != 0 && !HavePages)
                    throw new ArgumentException(nameof(CurrentPageNo));
                Set(ref currentPageNo, value)
            }
        }
    

    现在当前页面已经改变,我们需要减去新的学生列表。这应该在后台完成而不阻塞 UI 线程。添加CurrentPageNo

            set
            {
                if (value < 0)
                    throw new ArgumentException(nameof(CurrentPageNo));
                if (value >= TotalPages && HavePages)
                    throw new ArgumentException(nameof(CurrentPageNo));
                if (value != 0 && !HavePages)
                    throw new ArgumentException(nameof(CurrentPageNo));
                if (Set(ref currentPageNo, value)) // если изменения были...
                    PopulateCurrentPage().IgnoreResult(); // IgnoreResult напишем позже
            }
    

    我们还需要一个存储学生列表的属性:

        IEnumerable<StudentVM> currentPage;
        public IEnumerable<StudentVM> CurrentPage
        {
            get { return currentPage; }
            private set { Set(ref currentPage, value); }
        }
    

    以及执行更新的代码。他很复杂。

        // токен для остановки бегущего обновления
        CancellationTokenSource populationTaskCts = null;
        async Task PopulateCurrentPage()
        {
            // если старое обновление ещё бежит, отменяем его
            populationTaskCts?.Cancel();
            // начиная с этой точки, старое обновление нам не помешает
            CurrentPage = null;
            if (!HavePages)
                return;
            using (var cts = new CancellationTokenSource())
            {
                // теперь мы - текущее обновление
                populationTaskCts = cts;
                var workPageNo = CurrentPageNo; // может поменяться в процессе
    
                try
                {
                    // асинхронно получаем модельный список
                    var modelPage = await Task.Run(() =>
                        GetStudentsFromModel(workPageNo, cts.Token), cts.Token);
                    if (cts.IsCancellationRequested)
                        return;
                    // создаём VM-объекты в UI-потоке
                    var vmPage = modelPage.Select(p => new StudentVM(p.Name, p.ImageUri))
                                          .ToList();
                    if (cts.IsCancellationRequested)
                        return;
                    // если мы оказались тут, то мы всё ещё текущее обновление
                    Debug.Assert(workPageNo == CurrentPageNo);
                    CurrentPage = vmPage; // и можем присвоить результат
                }
                catch (OperationCanceledException) when (cts.IsCancellationRequested)
                {
                    // ничего не делаем, нас отменили
                }
                finally
                {
                    // если мы текущее обновление, убираем за собой токен
                    if (cts == populationTaskCts)
                        populationTaskCts = null;
                    // в противном случае там чужой токен, его не трогаем
                }
            }
        }
    

    我们还需要一个模型实例和一个GetStudentsFromModel读取它们的过程:

        StudentListModel model = new StudentListModel();
    
        const int pageSize = 10;
        IEnumerable<StudentModel> GetStudentsFromModel(int pageNo, CancellationToken ct)
        {
            // make sure it's materialized on background thread
            return model.GetAllStudents().Skip(pageNo * pageSize).Take(pageSize).ToList();
        }
    

    它还需要(稍后)计算页数:

        int GetPageCount(CancellationToken ct)
        {
            var studentCount = model.GetAllStudents().Count();
            return (int)Math.Ceiling((double)studentCount / pageSize);
        }
    

    现在这些过程是同步的,但如果您的模型将公开异步接口(如新 EF 所做的那样),则需要将它们设为异步。

    更远。我们需要一个命令来改变当前页面。

        public ICommand RequestPageChange { get; }
    

    及其实施:一种可行的方法:

        void OnPageChangeRequest(int newPage)
        {
            if (!HavePages)
                return;
            if (newPage < 0 || newPage >= TotalPages)
                return; // log an error?
            CurrentPageNo = newPage;
        }
    

    您必须将命令绑定到构造函数中的实现。同时,我们开始吧:

        public StudentListVM()
        {
            RequestPageChange = new RelayCommand<int>(OnPageChangeRequest);
        }
    

    (类RelayCommand几乎无处不在,我稍后再给)。

    是的,我们还需要在构造函数中开始统计页数和初始填充:

        public StudentListVM()
        {
            RequestPageChange = new RelayCommand<int>(OnPageChangeRequest);
            StartInitialPopulate().IgnoreResult();
        }
    
        async Task StartInitialPopulate()
        {
            TotalPages = await Task.Run(() => GetPageCount(CancellationToken.None));
            currentPageNo = 0;
            await PopulateCurrentPage();
        }
    }
    

    似乎什么都没有忘记。这个类原来太大了,也许将它重构成小块是有意义的。

    我们还在这里提到RelayCommand:

    public class RelayCommand<T> : ICommand
    {
        public RelayCommand(Action<T> onExecute) { OnExecute = onExecute; }
    
        public event EventHandler CanExecuteChanged;
        public bool CanExecute(object parameter) => true;
        public void Execute(object parameter) => OnExecute((T)parameter);
    
        readonly Action<T> OnExecute;
    }
    

    和功能IgnoreResult:

    public static class TaskExtgensions
    {
        public static void IgnoreResult(this Task t) { }
    }
    

    到此有了视图模型,似乎一切都解决了,让我们继续看视图。

    我们将视图模型附加到视图,如下所述:

    应用程序.xaml:

    <Application x:Class="Pages.App"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:local="clr-namespace:Pages">
    </Application>
    

    应用程序.xaml.cs:

    using System.Windows;
    
    using Pages.View;
    using Pages.VM;
    
    namespace Pages
    {
        public partial class App : Application
        {
            StudentListVM mainVM = new StudentListVM();
    
            protected override void OnStartup(StartupEventArgs e)
            {
                base.OnStartup(e);
                new MainWindow() { DataContext = mainVM }.Show();
            }
        }
    }
    

    现在让我们转到 MainWindow.xaml。开始:

    <Window x:Class="Pages.View.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:view="clr-namespace:Pages.View"
            xmlns:vm="clr-namespace:Pages.VM"
            Title="Pages" Height="600" Width="800">
    

    На нашем мок-апе есть явно две области: нижняя маленькая со списком страниц, и верхняя большая с содержимым текущей страницы. Это напрашивается на Grid:

        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="*"/>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
    

    Теперь, верхний элемент. Он показывает список элементов, без текущего элемента и всего такого. Так что это ItemsControl:

            <ItemsControl ItemsSource="{Binding CurrentPage}">
    

    Теперь, как расположены элементы в нём? Они идут не в столбик, а «перетекают» по горизонтали в следующую строку. Отлично, значит, нам нужно установить в ItemsPanel подходящий контейнер:

                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <WrapPanel IsItemsHost="True"/>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
    

    Как выглядит отдельный элемент? Это не стандартный ToString(), это текст с картинкой. Напишем для этого ItemTemplate:

                <ItemsControl.ItemTemplate>
                    <DataTemplate DataType="{x:Type vm:StudentVM}">
                        <!-- фиксированный размер элемента и рамка -->
                        <Border Width="150" Height="200" BorderThickness="1"
                                BorderBrush="Gray" CornerRadius="5">
                            <DockPanel LastChildFill="True" Background="LightGray">
                                <!-- текст прижмём вниз и центрируем -->
                                <TextBlock DockPanel.Dock="Bottom" Text="{Binding Name}"
                                           TextAlignment="Center"/>
                                <!-- остальное место занимает картинка -->
                                <Image Source="{Binding ImageUri}"/>
                            </DockPanel>
                        </Border>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
    

    Вроде бы ничего не забыли.

            </ItemsControl>
    

    Окей, с таблицей справились, теперь нам нужен список страниц. Откуда его взять? У нас по идее есть только количество страниц, нужно его превратить в список при помощи конвертера. Затем, мы ведь не хотим показывать все страницы? Их может быть очень много. Будем показывать первые страницы, последние страницы и страницы вокруг текущей.

    Засучим рукава и вперёд!

    Для начала, тип для описания страницы или заполнителя:

    enum PageEntryType { Normal, Current, Ellipsis }
    
    struct PageEntry
    {
        public int PageNumber { get; }
        public PageEntryType Type { get; }
        public PageEntry(int num, PageEntryType type) { PageNumber = num; Type = type; }
    }
    

    Ну и сам конвертер. Надеюсь, я не напутал с вычислениями.

    Нам нужен IMultiValueConverter, потому что у нас два входных значения.

    class PageListConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter,
                              CultureInfo culture)
        {
            int currentPage = (int)values[0];
            int numberOfPages = (int)values[1];
            return RecalcList(currentPage, numberOfPages);
        }
    
        IEnumerable<PageEntry> RecalcList(int currentPage, int numberOfPages)
        {
            const int pagesAroundCurrent = 3; // сколько страниц вокруг текущей
            const int pagesAroundEnd = 2; // сколько страниц по краям
    
            var min = Math.Max(0, currentPage - pagesAroundCurrent);
            var max = Math.Min(numberOfPages - 1, currentPage + pagesAroundCurrent);
    
            // перекрывается список вокруг текущей страницы со списком у левого края?
            bool separateLeftEnd = pagesAroundEnd + 1 < min;
            if (!separateLeftEnd)
                min = 0;
    
            // перекрывается список вокруг текущей страницы со списком у правого края?
            bool separateRightEnd = numberOfPages - 1 - pagesAroundEnd - 1 > max;
            if (!separateRightEnd)
                max = numberOfPages - 1;
    
            if (separateLeftEnd)
            {
                for (int n = 0; n < pagesAroundEnd; n++)
                    yield return new PageEntry(n, PageEntryType.Normal);
                // между списками разрыв - многоточие
                yield return new PageEntry(-1, PageEntryType.Ellipsis);
            }
    
            for (int n = min; n <= max; n++)
                yield return new PageEntry(n, (n == currentPage) ? PageEntryType.Current :
                                                                   PageEntryType.Normal);
    
            if (separateRightEnd)
            {
                // между списками разрыв - многоточие
                yield return new PageEntry(-1, PageEntryType.Ellipsis);
                for (int n = numberOfPages - pagesAroundEnd; n < numberOfPages;  n++)
                    yield return new PageEntry(n, PageEntryType.Normal);
            }
        }
    
        public object[] ConvertBack(object value, Type[] targetTypes, object parameter,
                                    CultureInfo culture)
        {
            throw new NotSupportedException();
        }
    }
    

    Отлично, список у нас есть, теперь его нужно показать. Как показывать список? Возвращаемся к нашему недописанному XAML'у. Нам нужен ItemsControl, как обычно. Кладём его во вторую строку и добавим небольшой маргин.

            <ItemsControl Grid.Row="1" Margin="5">
    

    В ресурсы положим конвертер

                <ItemsControl.Resources>
                    <view:PageListConverter x:Key="PageListConverter"/>
                </ItemsControl.Resources>
    

    а элементы берём из количества страниц и номера текущей, с использованием этого конвертера:

                <ItemsControl.ItemsSource>
                    <MultiBinding Converter="{StaticResource PageListConverter}">
                        <Binding Path="CurrentPageNo"/>
                        <Binding Path="TotalPages"/>
                    </MultiBinding>
                </ItemsControl.ItemsSource>
    

    Окей, дальше нам нужно эти элементы расположить по горизонтали. Для этого сгодится StackPanel. Саму панель тоже центрируем:

                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <StackPanel Orientation="Horizontal" HorizontalAlignment="Center"
                                    IsItemsHost="True"/>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
    

    Теперь отображение каждого элемента списка. У нас есть три варианта отображения: обыкновенная страница показывается в виде ссылки, текущая — без ссылки, но жирным шрифтом, а на месте для многоточия должно появиться многоточие. Выбор из этих трёх вариантов делаем при помощи привязки Visibility блока к значению нашего элемента через конвертер. Конвертер мы напишем позже, он будет делать видимым только один из трёх нужных элементов. Сам конвертер мы добавим в ресурсы ItemsControl'а:

                <ItemsControl.Resources>
                    <view:PageListConverter x:Key="PageListConverter"/>
                    <view:PageEntryTypeToVisibilityConverter x:Key="PageEntryTypeToVisibilityConverter"/>
                </ItemsControl.Resources>
    

    Продолжаем:

                <ItemsControl.ItemTemplate>
                    <DataTemplate>
    

    Располагаем элементы один на другом, видимым будет только один.

                        <Grid Margin="5,2">
    

    Первый вариант: нормальное отображение. Нам нужна гиперссылка. По нажатию на неё вызовем обработчик из code-behind.

                            <TextBlock Visibility="{Binding Converter={StaticResource PageEntryTypeToVisibilityConverter},
                                                            ConverterParameter={x:Static view:PageEntryType.Normal}}">
                                <Hyperlink Click="OnPageChangeRequest"><Run Text="{Binding PageNumber, Mode=OneWay}"/></Hyperlink>
                            </TextBlock>
    

    Второй вариант: текущая страница. Вместо ссылки — TextBlock с жирным шрифтом.

                            <TextBlock Visibility="{Binding Converter={StaticResource PageEntryTypeToVisibilityConverter},
                                                            ConverterParameter={x:Static view:PageEntryType.Current}}"
                                       FontWeight="Bold" Text="{Binding PageNumber, Mode=OneWay}"/>
    

    Ну и третий вариант — просто многоточие.

                            <TextBlock Visibility="{Binding Converter={StaticResource PageEntryTypeToVisibilityConverter},
                                                            ConverterParameter={x:Static view:PageEntryType.Ellipsis}}"
                                       Text="..."/>
    

    Вот и всё с отображением элемента.

                        </Grid>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
    

    Больше в XAML'е делать нечего.

        </Grid>
    </Window>
    

    Заимплементируем обработчик клика по ссылке. Он лежит в классе MainWindow

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    
        void OnPageChangeRequest(object sender, RoutedEventArgs e)
        {
    

    Нам нужно где-то взять команду. Чтобы не лазить по DataContext'у, сделаем простой трюк: привяжем эту команду в свободное свойство. Например, в Tag. (Это мы сделаем потом, снова-таки в XAML'е.)

            var command = (ICommand)Tag; // прочитали оттуда команду
            if (command == null)
                return;
    
            var hyperlink = (Hyperlink)sender;
    

    Номер страницы можно вытащить из DataContext'а гиперссылки.

            var pageNo = ((PageEntry)hyperlink.DataContext).PageNumber;
            command.Execute(pageNo);
        }
    }
    

    Возвращаемся в XAML и дописываем Tag:

    <Window x:Class="Pages.View.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:view="clr-namespace:Pages.View"
            xmlns:vm="clr-namespace:Pages.VM"
            Title="Pages" Height="600" Width="800"
            Tag="{Binding RequestPageChange}">
    

    Последняя недописанная вещь — PageEntryTypeToVisibilityConverter. Он очень простой:

    public class PageEntryTypeToVisibilityConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter,
                              CultureInfo culture)
        {
            PageEntryType expectedType = (PageEntryType)parameter;
            PageEntryType actualType = ((PageEntry)value).Type;
            return expectedType == actualType ? Visibility.Visible : Visibility.Collapsed;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter,
                                  CultureInfo culture)
        {
            throw new NotSupportedException();
        }
    }
    

    Запускаем и получаем:

    兔子,它们充满了整个星球


    是的,我们也让它在列表为空时显示某种合理的消息。这很简单。让我们回到 XAML 并向外部添加另一个元素Grid:

            <TextBlock FontSize="24" Grid.Row="0" Text="No students found so far..."
                       TextAlignment="Center" VerticalAlignment="Center"/>
    

    但是这样这个元素就会一直可见,只有在没有页面的时候我们才需要它。没问题,让我们绑定到HavePages. 我们需要将其转换为Visibility. 但是标准的BooleanToVisibilityConverter转换方向错误,所以让我们从这里窃取转换器:

    public class BooleanConverter<T> : IValueConverter
    {
        public BooleanConverter(T trueValue, T falseValue)
        {
            OnTrue = trueValue;
            OnFalse = falseValue;
        }
    
        public T OnTrue { get; set; }
        public T OnFalse { get; set; }
    
        public virtual object Convert(object value, Type targetType, object parameter,
                                      CultureInfo culture)
        {
            if (!(value is bool))
                return DependencyProperty.UnsetValue;
            return ((bool)value) ? OnTrue : OnFalse;
        }
    
        public virtual object ConvertBack(object value, Type targetType, object parameter,
                                          CultureInfo culture)
        {
            throw new NotSupportedException();
        }
    }
    
    public class BooleanToVisibilityConverter : BooleanConverter<Visibility>
    {
        public BooleanToVisibilityConverter() : base(Visibility.Visible, Visibility.Collapsed) {}
    }
    

    现在你可以这样写:

            <TextBlock FontSize="24" Grid.Row="0" Text="No students found so far..."
                       TextAlignment="Center" VerticalAlignment="Center"
                       Visibility="{Binding HavePages,
                               Converter={StaticResource BooleanToVisibilityConverter}}"/>
    

    你只需要将它放在窗口资源中:

    <Window x:Class="Pages.View.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:view="clr-namespace:Pages.View"
            xmlns:vm="clr-namespace:Pages.VM"
            xmlns:sys="clr-namespace:System;assembly=mscorlib"
            Title="Pages" Height="600" Width="800"
            Tag="{Binding RequestPageChange}">
        <Window.Resources>
            <view:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"
                                               OnTrue="Collapsed" OnFalse="Visible"/>
        </Window.Resources>
    

    美丽的进一步指导就在你身上。

    • 28

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    Python 3.6 - 安装 MySQL (Windows)

    • 1 个回答
  • Marko Smith

    C++ 编写程序“计算单个岛屿”。填充一个二维数组 12x12 0 和 1

    • 2 个回答
  • Marko Smith

    返回指针的函数

    • 1 个回答
  • Marko Smith

    我使用 django 管理面板添加图像,但它没有显示

    • 1 个回答
  • Marko Smith

    这些条目是什么意思,它们的完整等效项是什么样的

    • 2 个回答
  • Marko Smith

    浏览器仍然缓存文件数据

    • 1 个回答
  • Marko Smith

    在 Excel VBA 中激活工作表的问题

    • 3 个回答
  • Marko Smith

    为什么内置类型中包含复数而小数不包含?

    • 2 个回答
  • Marko Smith

    获得唯一途径

    • 3 个回答
  • Marko Smith

    告诉我一个像幻灯片一样创建滚动的库

    • 1 个回答
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Алексей Шиманский 如何以及通过什么方式来查找 Javascript 代码中的错误? 2020-08-03 00:21:37 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    user207618 Codegolf——组合选择算法的实现 2020-10-23 18:46:29 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5